Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

SQLite transaction stays open when its task is cancelled

Geschlossen Anfängerfreundlich
#188 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

@jrderuiter arbeitet bereits daran.

Seit 12.10.2026.

  • #189 von @jrderuiter — offen

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
88/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
python, sqlite
Bereich
database

Rechercherichtung

Lies mautrix/util/async_db/aiosqlite.py, insbesondere TxnConnection.transaction(), und bestätige, wie die Cancellation den Exception-Handler verlässt. Führe die bereitgestellte Reproduktion aus: Brich slow() während der Transaktion ab und starte dann eine weitere Transaktion auf der Verbindung. Erledigt ist die Aufgabe, wenn die Cancellation die erste Transaktion zurückrollt und die zweite Transaktion ohne den Fehler wegen verschachtelter Transaktionen abgeschlossen wird.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

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.

Vorherrschende Sprache
Python
Sterne
251
Forks
85
Ø Merge
1 Std. 53 Min.
Gemergte PRs (30 T.)
1

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus mautrix/python

Alle Issues in mautrix/python

Ähnliche Issues

Weitere Issues zu Python

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.