SQLite transaction stays open when its task is cancelled
評估
研究方向
閱讀 mautrix/util/async_db/aiosqlite.py,尤其是 TxnConnection.transaction(),並確認取消操作如何退出其例外處理器。執行提供的重現步驟:在交易期間取消 slow(),然後在該連線上啟動另一個交易。取消操作回滾第一個交易,且第二個交易完成時沒有巢狀交易錯誤,即為完成。
由索引模型根據 Issue 內容生成。
描述
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:
try:
yield
except Exception:
await self.rollback()
raise
else:
await self.commit()
finally:
in_transaction.reset(token)
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
import asyncio, os
from mautrix.util.async_db import Database
async def main():
db = Database.create("sqlite:///" + os.path.abspath("repro.db"))
await db.start()
await db.execute("CREATE TABLE IF NOT EXISTS t (x INT)")
async def slow():
async with db.acquire() as conn, conn.transaction():
await conn.execute("INSERT INTO t VALUES (1)")
await asyncio.sleep(10)
task = asyncio.create_task(slow())
await asyncio.sleep(0.2)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
async with db.acquire() as conn, conn.transaction():
await conn.execute("INSERT INTO t VALUES (2)")
asyncio.run(main())
The last transaction fails with sqlite3.OperationalError: cannot start a transaction within a transaction.
Fix
Roll back on BaseException instead of Exception.
- 主要語言
- Python
- 星號
- 251
- 分支
- 85
- PR 合併指標
- 30 天內沒有已合併 PR
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 沒有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
mautrix/python 的其他 Issue
-
難度 5/5 一週以上 新手友好度 35/100
-
難度 5/5 一週以上 新手友好度 30/100
-
using inspect.unwrap on `maurix.types.Obj` places the object into a state where serializing raises a RecursionError可能已有人在做 @Deln0r 於 152 天前認領。 未關閉bug
難度 2/5 1-3 小時 新手友好度 45/100
-
難度 5/5 一週以上 新手友好度 25/100
-
難度 4/5 3-5 天 新手友好度 30/100
相似的 Issue
-
難度 1/5 1-3 小時 新手友好度 88/100
gradio-app/gradio#13964 ·
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 93/100
BSData/horus-heresy-3rd-edition#3232 · 1 則留言 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 78/100
jbacalso24/mimry#123 ·
維護者通常 1 天內回覆
-
p:3-mid pydanty:bug pydanty:is-working
難度 2/5 1-3 小時 新手友好度 76/100
pydantic/pydantic-ai#10153 · 1 則留言 ·
維護者通常 1 天內回覆
-
good first issue priority: medium size: S testing
難度 2/5 1-3 小時 新手友好度 85/100
cubrid-lab/cubrid-cookbook-python#316 ·
維護者通常 1 天內回覆