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
SQLite transaction stays open when its task is cancelled #188
A cancelled task can leave an SQLite transaction open. After that, every new transaction on the connection fails with cannot start a transaction within a transaction.
Cause
TxnConnection.transaction() in mautrix/util/async_db/aiosqlite.py rolls back only on Exception:
asyncio.CancelledError is not an Exception. When a task is cancelled inside the transaction, neither rollback() nor commit() runs. The connection goes back to the pool with the transaction still open. The next BEGIN TRANSACTION fails.
Impact
We use mautrix 0.21.1 through Hermes Agent, which keeps the Matrix crypto store in SQLite and cancels work with timeouts. After the first cancellation inside a crypto store transaction, the bot cannot share room keys, and every encrypted message fails.
Reproduce
importasyncio, osfrommautrix.util.async_dbimportDatabaseasyncdefmain():
db=Database.create("sqlite:///"+os.path.abspath("repro.db"))
awaitdb.start()
awaitdb.execute("CREATE TABLE IF NOT EXISTS t (x INT)")
asyncdefslow():
asyncwithdb.acquire() asconn, conn.transaction():
awaitconn.execute("INSERT INTO t VALUES (1)")
awaitasyncio.sleep(10)
task=asyncio.create_task(slow())
awaitasyncio.sleep(0.2)
task.cancel()
try:
awaittaskexceptasyncio.CancelledError:
passasyncwithdb.acquire() asconn, conn.transaction():
awaitconn.execute("INSERT INTO t VALUES (2)")
asyncio.run(main())
The last transaction fails with sqlite3.OperationalError: cannot start a transaction within a transaction.
Activity