Files
hermes-agent/tests
teknium1 87bb0d3827 fix(state): a closing writer keeps its WAL generation until SQLite's own close (#121429)
SessionDB.close() lifts the OFD lock guard before sqlite3_close so a true
last close can still end the generation. When a stray in-process
open()/close() has already cancelled the handle's POSIX locks (the case
the guard exists for), lifting the OFD copy leaves the still-open
connection with no lock at all. A sibling closing in that gap takes
EXCLUSIVE and unlinks -wal/-shm under it, and every opener in the
meantime refuses with DeletedWalGenerationError.

release() now re-takes SQLite's own process-owned POSIX read lock on each
range before it drops the OFD copy. That is the lock SQLite still thinks
it holds. The re-take cannot be refused, because our OFD lock already
excludes writers. SQLite's close upgrades or drops the lock itself, so a
true last close still unlinks the generation.

Repro: the torture chamber's lock_cancellation episode on CI
(job 107586407677: "lock_cancellation-tui held state.db-shm (deleted)").
Deterministic with a sleep injected between release() and the connection
close: base red 4/4, fix green 4/4. The new lifecycle test runs a sibling
sqlite3 close at that seam: red on base (-shm unlinked), green on the fix,
and it checks that the last close still removes -wal.
2026-09-26 11:32:10 -07:00
..