libdb 2026.09.5
A correctness release that executes all six follow-up actions from an in-depth review conducted in the voices of Keith Bostic, Margo Seltzer, Michael Bray, and Michael Cahill. Three real bugs were found — none of which the existing test suite caught.
Bugs fixed
os_aio cross-reap — a durability bug, reproduced
__memp_aio_drain drained by count off a process-wide, untagged completion queue. Four __memp_sync_int callers (checkpoint, trickle, DB->sync, DB_SYNC_ALLOC) can overlap, and mtx_ckp serializes checkpoints against each other only — so one caller could reap another's completions and finish a slot whose own write never completed, clearing BH_DIRTY for an in-flight write: a false durable frontier plus a write-after-free of the pgout copy. Reproduced under assertion, not merely argued.
Fixed with an exclusive-use MUTEX_TRYLOCK latch: one consumer of the completion queue at a time, the loser writes synchronously. It is never waited on, so it adds no lock-ordering edge. The latch lives inside struct __db_aio_context, and a compile-time guard now pins sizeof(struct __db_mpool) — because env_sig.c hashes that struct into the build signature unconditionally, so growing it would make existing environments refuse to attach, a break abidiff cannot see.
st_nsnapshot underflowed and wrapped
The counter an operator would naturally alarm on for snapshot/SSI retention read ~4.29 × 10⁹. __txn_end has two sites that park a transaction detail for later reclamation; the SSI one never incremented while both reclaim paths decremented. It now tracks a bounded sawtooth whose ceiling is the documented fraction of the lock-object table.
A test that had never run
mvcc_purge_visible — the correctness gate for obsolete-MVCC-version reclamation — was silently skipped for its entire existence: its run directory path collided with the compiled driver binary, so the directory creation failed and the harness still exited non-zero without naming a failing test. Fixed, and aio_concurrent_sync (which was listed but likewise never invoked) is now wired in.
Serializable-isolation assurance
Two new tests close gaps identified in review:
- Marker-GC safety — a write skew whose only surviving evidence at the decisive moment is one committed reader's SIREAD marker, run against all three real garbage-collection triggers. 0 anomalies in 120 iterations; neutering the oldest-reader predicate makes 40/40 iterations commit the skew. At plain snapshot isolation the same schedule must produce the anomaly (120/120), so the test cannot pass vacuously.
- A pivot cannot survive a crash —
SIGKILLat four points inside commit, then recovery. The result is structurally stronger than "no anomaly observed": a doomed transaction never reaches the log-write points at all, because the conflict is returned upstream of the commit record. Verified with a legal transaction armed at the same points to prove the injection works, and with the pivot check neutered to prove the test has teeth. The crash hook compiles to nothing outside diagnostic builds.
Operability
Seven in-use / max (N% utilized) signals across the lock, transaction, and mutex regions, in *_stat_print and db_stat -c/-t/-x, all derived at read time — plus a documented playbook of thresholds, remedies, and the warning that monitors must not use DB_STAT_CLEAR. Neutering the reclaimer crosses the documented 0.8 threshold roughly 500 transactions before exhaustion, which is the point. No statistics structure grew, deliberately.
Design documentation
docs/design/global-invariants.md— the invariants that hold across subsystems, organized by checkpoint, crash, and region re-attach, with the global lock order stated as a single partial order, nine dangerous subsystem pairs, per-invariant test coverage, and eleven named coverage gaps.- RFC 0005 — optional row-level (rather than page-level) conflict tracking, to reduce false aborts. Names phantom prevention as a blocking precondition, since page granularity prevents scan-then-insert phantoms by accident.
- RFC 0006 — a chain-replicated WAL as a shared log for multi-master scale-out (CORFU/Tango lineage). It identifies a blocking objection (redo records carry a page-LSN precondition) and prior art that already occupies the design space, and recommends against itself as an implementation plan.
Known issue
With the opt-in DB_MPOOL_AIO enabled (it is off by default), a concurrent checkpoint/trickle/sync workload can deadlock: the latch holder blocks acquiring a new buffer while holding deferred-write pins, because the deferred path only drains once its window is full. The cycle is fully identified and two candidate fixes are named. No data is lost in any observed occurrence — recovery and verification are clean every time — and the default path is unaffected.
Compatibility
On-disk, log, region, and public-ABI formats unchanged; the build signature is byte-identical, so existing environments attach normally. soname unchanged.