Skip to content

Commit

Permalink
Reproduce race-condition between close & prepare
Browse files Browse the repository at this point in the history
  • Loading branch information
akash-akya committed Oct 27, 2022
1 parent 4fc3a55 commit f01563f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
8 changes: 8 additions & 0 deletions c_src/sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -135367,6 +135367,12 @@ static int sqlite3LockAndPrepare(
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
return SQLITE_MISUSE_BKPT;
}
// sleep only for insert stmt
if (strncmp(zSql, "insert into debug", 17) == 0) {
printf("sqlite3LockAndPrepare(): do not acquire the mutex, wait for sqlite3LeaveMutexAndCloseZombie() execute\n");
sqlite3_sleep(1000);
printf("sqlite3LockAndPrepare(): done waiting, proceeding with the execution\n");
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
do{
Expand Down Expand Up @@ -172100,6 +172106,8 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
db->xAutovacDestr(db->pAutovacPagesArg);
}
sqlite3_mutex_leave(db->mutex);
printf("sqlite3LeaveMutexAndCloseZombie(): critical-section execution is done, the mutex is released. Wait for sqlite3LockAndPrepare() to proceeds before we free db\n");
sqlite3_sleep(1500);
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
assert( sqlite3LookasideUsed(db,0)==0 );
Expand Down
15 changes: 15 additions & 0 deletions test/exqlite/timeout_segfault_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule Exqlite.TimeoutSegfaultTest do
use ExUnit.Case

alias Exqlite.Sqlite3

setup do
{:ok, path} = Temp.path()
on_exit(fn -> File.rm(path) end)
Expand Down Expand Up @@ -36,4 +38,17 @@ defmodule Exqlite.TimeoutSegfaultTest do
end)
|> Stream.run()
end

test "race condition", %{path: path} do
{:ok, conn} = Sqlite3.open(path)
:ok = Sqlite3.execute(conn, "create table debug(id integer)")

spawn_link(fn ->
Sqlite3.prepare(conn, "insert into debug(id) values (1)")
end)

# ensure `Sqlite3.prepare()` is executed before we attempt to close the connection
Process.sleep(100)
:ok = Sqlite3.close(conn)
end
end

0 comments on commit f01563f

Please sign in to comment.