You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sqlite3: deadlock when threads share a connection that has Python callbacks #161065
A sqlite3 connection shared between threads (check_same_thread=False, SQLite in serialized mode, sqlite3.threadsafety == 3) deadlocks the whole process if it has a Python callback registered (function, aggregate, collation, authorizer, progress handler or trace callback). SQLite invokes the callback from sqlite3_step() with the connection mutex held, and the callback then waits for the GIL in PyGILState_Ensure(); meanwhile another thread holds the GIL and blocks on the same connection mutex in an SQLite call the module makes without releasing the GIL, for example sqlite3_column_int64() in _pysqlite_fetch_one_row(), sqlite3_bind_*(), sqlite3_errmsg() or sqlite3_set_authorizer().
importsqlite3, threadingcx=sqlite3.connect(":memory:", check_same_thread=False)
cx.create_function("f", 1, lambdax: x)
cx.execute("create table t(x)")
cx.executemany("insert into t values(?)", [(i,) foriinrange(1000)])
defwork(n):
# different SQL in each thread, so no cached statement is sharedforiinrange(100):
cx.execute(f"select f(x) from t limit {n+i}").fetchall()
threads= [threading.Thread(target=work, args=(n,)) fornin (10000, 20000)]
fortinthreads:
t.start()
fortinthreads:
t.join() # never returns
The script should finish; instead it hangs within a second and cannot be interrupted with Ctrl-C. gh-86864 was the same lock inversion in Connection.close(), fixed by releasing the GIL around sqlite3_close_v2().
Activity