From 7f58f1cab3f73e4ea5bdeff3c85e7927e9c9ed8f Mon Sep 17 00:00:00 2001 From: Cobra Date: Tue, 7 Apr 2026 12:23:38 -0400 Subject: [PATCH] Fix StateManager deadlock with explicit BEGIN IMMEDIATE + retry with conn: context manager in Python sqlite3 doesn't respect busy_timeout for the implicit BEGIN; under concurrent subprocess writes the transaction would fail immediately. Replace with explicit BEGIN IMMEDIATE + retry loop (6 attempts, 0.5s back-off) to handle WAL write contention. --- core/state.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/core/state.py b/core/state.py index c050faf..df886f8 100644 --- a/core/state.py +++ b/core/state.py @@ -250,12 +250,29 @@ class StateManager: return conn = self._get_write_conn() - try: - with conn: + for attempt in range(6): + try: + conn.execute("BEGIN IMMEDIATE") for sql, params in batch: conn.execute(sql, params) - except Exception: - logger.exception("StateManager flush failed (%d ops)", len(batch)) + conn.execute("COMMIT") + return + except sqlite3.OperationalError as e: + try: + conn.execute("ROLLBACK") + except Exception: + pass + if attempt < 5: + time.sleep(0.5 * (attempt + 1)) + else: + logger.error("StateManager flush failed after 6 attempts (%d ops): %s", len(batch), e) + except Exception: + try: + conn.execute("ROLLBACK") + except Exception: + pass + logger.exception("StateManager flush failed (%d ops)", len(batch)) + return def _writer_loop(self) -> None: """Background loop: flush write queue every FLUSH_INTERVAL seconds."""