From 81f60a0c84c12ab60b27ab625ee16436d911bfde Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:06:06 -0700 Subject: [PATCH] fix(gateway): close readiness-probe SQLite connection deterministically Sibling of the #69678/#69567 ledger leak class found while widening the sweep: _probe_state_db used 'with sqlite3.connect(...)', whose context manager only commits/rolls back and never closes, leaking one connection (db fd) per health poll in the long-running gateway. Wrap the connection in contextlib.closing so every probe closes deterministically. --- gateway/readiness.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gateway/readiness.py b/gateway/readiness.py index 379e074bb40..d49ea820482 100644 --- a/gateway/readiness.py +++ b/gateway/readiness.py @@ -4,6 +4,7 @@ from __future__ import annotations import shutil import sqlite3 +from contextlib import closing from pathlib import Path from typing import Any @@ -31,8 +32,12 @@ def _probe_state_db(home: Path) -> dict[str, Any]: # A readiness probe must never compete with normal state writers. A # read-only schema query still catches unreadable/corrupt databases # without taking a write reservation on every health poll. + # ``closing(...)`` is required: sqlite3's connection context manager + # only commits/rolls back — it never closes, so a bare ``with + # sqlite3.connect(...)`` leaks one connection (and its fds) per + # health poll in the long-running gateway (#69678/#69567 bug class). uri = f"file:{path.as_posix()}?mode=ro" - with sqlite3.connect(uri, uri=True, timeout=1.0) as conn: + with closing(sqlite3.connect(uri, uri=True, timeout=1.0)) as conn: conn.execute("PRAGMA query_only = ON") conn.execute("SELECT name FROM sqlite_master LIMIT 1").fetchone() return _check("ok")