Files
codebase-memory-mcp/tests
Martin Vogel f9ce38658b fix(store): one process-wide section for a query connection's first access
On an idle WAL database (no connection open, -shm reset) the first read of a
new connection runs WAL recovery: walIndexRecover rebuilds the shared
wal-index header under SQLite's write lock. A second connection of the same
process opening at that moment reads that header lock-free at the start of
walTryBeginRead, before it takes its read lock. Across processes SQLite's
file locks order the two; between the daemon's request threads nothing did.
TSan reported exactly that pair three times in CI (2026-10-06 on #2458's
tsan-arm leg, 2026-10-07 twice on #2348's macOS leg), from concurrent
index_repository requests reading the project record through
cbm_store_open_path_query.

cbm_store_open_path_query now opens and probes the database (the plain
read-only open, its first read, and the immutable fallback) inside
SQLITE_MUTEX_STATIC_APP1, the process-wide mutex SQLite reserves for the
application. The probe is one sqlite_master read, so the section is short;
the queries that follow run outside it, as before.

Regression test store_query_first_access_is_one_process_section: a test
seam holds one opener inside the section, and sqlite3_mutex_try on the
section's mutex must then report SQLITE_BUSY. It fails without the lock
(try returns SQLITE_OK) and passes with it. SQLite's Windows build reports
BUSY from sqlite3_mutex_try unconditionally, so the failing case is shown on
POSIX; the locking code is the same on every platform.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-07 19:20:08 +02:00
..