libdb 2026.09.9
A defect-fix release. Every fix here was found by a gate added in v2026.09.8 —
each of those three gates failed on its first run against master, which is what
they were built to do.
Fixed: --disable-mutexsupport had never built (U7)
Three stacked defects, each only visible once the previous one was fixed, which is why
a single error message understated it:
src/dbinc/os.hdeclared prototypes without the types they name. It includes
dbinc_auto/os_ext.h, which declares the atomic helpers in terms ofdb_atomic_t
andatomic_value_t. Those live indbinc/atomic.h, reachable only through
dbinc/mutex_int.h— andmutex.h:12includes that only under
HAVE_MUTEX_SUPPORT. So the no-mutex build reached the prototypes with the types
undefined.- The no-mutex
MUTEX_*stubs could not be used as values. They expanded to
(mutex) = (mutex), an assignment expression. Upstream's comment explains that form
exists so if-then-else blocks still parse — fine for statement use. But our os_aio
cross-reap latch doesMUTEX_TRYLOCK(...) == 0atmp_sync.c:396, and comparing an
assignment expression against 0 fails to compile. The stubs now expand to
((void)(mutex), 0)— valid as statement and value, returning the success code the
trylock contract specifies, which is the right answer when there is no mutex to
contend for. lock_stub.cwas missing two SSI stubs.configure.ac:1168substitutes
lock_stub.ofor the entireLOCK_OBJSset in a no-mutex build, so that file must
no-op every__lock_*entry point the tree calls — 59 of them. Our SSI work
added__lock_sicommitand__lock_sicleanuptolock.cbut only
__lock_sireap_lockersto the stub file.
That third one is the same shape as the exec-bit and manifest gaps this project keeps
finding: a hand-maintained second list with nothing checking it. The G14
configure-option sweep is now that check.
Fixed: DB_DIRECT_DB could not open a database (P2)
O_DIRECT requires a block-aligned transfer buffer. Every caller of
__fop_read_meta passed a plain stack array — u_int8_t mbuf[DBMETASIZE], 8 sites
across fop_rec.c and fop_util.c — carrying only scalar alignment. Measured:
0x7ffd3b755240, neither 512- nor 4096-aligned. The first metadata read failed
EINVAL, so no database opened at all.
Why this is worse than a configuration nobody builds. Whether the read fails
depends on the kernel tolerating an unaligned buffer for that particular call. I
measured DB_DIRECT_DB passing on one XFS/NVMe box and failing on another, both
with sectsz=512. So it is latent on a developer's machine and live on a deployment's
storage — and a green result proves nothing. An earlier note attributing this to
XFS-vs-other filesystems was wrong; measuring two boxes disproved it before the fix
was written, and that erratum is recorded.
Fixed at __fop_read_meta, the single choke point, so all eight call sites and any
future one are covered. Uses ALIGNP_INC (already in the tree) over an over-sized
stack buffer rather than an aligned heap allocation: nothing to free means no error
path can leak, which matters on the database-open path in every process. Gated on
DB_ENV_DIRECT_DB, so the default build is byte-for-byte unchanged.
The behaviour test alone was not sufficient, and the release says so
flag_behaviour's direct_db mode asserts O_DIRECT is really set on the descriptor
— the right assertion, and it passes. But it passed before the fix too, on hardware
whose kernel tolerates the unaligned buffer. On such a box it cannot distinguish fixed
from broken.
So test/c/p2_align.c asserts the mechanism: that ALIGNP_INC over the over-sized
buffer yields a 4096-aligned address where the bare array does not, and that
DBMETASIZE still fits after rounding. It reports honestly when the bare buffer
happens to be aligned rather than claiming a difference it did not observe. Declared
in test/MANIFEST so it cannot silently stop running.
Also in this release: the gates themselves (G12–G15)
Shipped in v2026.09.8 and worth restating, because they are why the two fixes above
exist:
- A scaling-shape gate (
test/bench/scale_shape_gate.sh) asserting monotonicity
rather than absolute throughput, which is robust to runner noise. It currently
FAILS at −68.2% at t=96 — correctly, because P1 is real and open. - A configure-option sweep covering all 54 options as swept / excluded-with-reason
/ failing, and checking every option is in one of those lists, so adding an option
forces a testing decision. - Behaviour tests for six runtime I/O and durability flags that previously had zero
test coverage.
Known issues, unchanged and open
- P1 — the
PGNO_BASE_MDallocation convoy.__db_newholds the metadata page
write-locked until commit, across its own fsync, because__TLPUTis a no-op for a
write lock inside a transaction. At t=96 bulk insert, 400 of 400 lock waits are on
page 0;new-orderp99 is 2,064 ms against WiredTiger's 182 ms on the same
device at the same page-read rate. This is the dominant cause of libdb's throughput
peaking at 8 threads and falling to 32% of that peak by 96. Deliberately not
rushed into this release: the metadata page holds the free list, so any fix is a
two-phase-locking argument, and a wrong one corrupts databases. - P3 —
DB_LOG_DIRECThas P2's defect at a different site.__log_writepasses
both a caller-supplied buffer and an arbitrary length to__os_io
(log_put.c:1453), violating twoO_DIRECTconstraints, so it needs its own
durability argument.direct_logremains XFAIL. - F1 — a transient Apple clang crash compiling
env_register.conmacos-14
(Abort trap: 6). An unmodified rerun of the identical commit passed and the job had
succeeded on master's previous 5 runs, so it is not reproducible. Not filed upstream:
a compiler-crash report needs the preprocessed source clang dumps into the runner's
temp directory, and that runner is destroyed with the job. Recorded with the action to
take if it recurs — capture the artifacts first, then file. - Unchanged:
T1–T6,S1(opt-inDB_MPOOL_AIO),S5,U1–U6,W1,B1.
Compatibility
No on-disk, log, region, or public-ABI change. __env_struct_sig() is 0xb86f77f0,
verified identical to v2026.09.8 with both arms measured in fresh build dirs; public
sizes remain 1744/552/2088/336. Existing environments attach unchanged. The
compatibility triplet stays 2026.0.9 and db_version() returns 2026,0,9, checked
against a built library.
Qualified from a pristine clone on a dedicated EC2 instance: default build, 32-bit
toolchain and meson available, --disable-mutexsupport build, flag tier (13 verdicts,
manifest OK), db tier, leak tier, exec-bit gate, and the manifest self-check.