Skip to content

mutex: lock-order checker compares latches within one environment only - #268

Merged
gburd merged 3 commits into
masterfrom
fix/lock-order-per-env
Nov 4, 2026
Merged

gburd merged 3 commits into
masterfrom
fix/lock-order-per-env

Conversation

@gburd

@gburd gburd commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

The lock-order checker (--enable-diagnostic only) compared mutex indices across environments. A mutex index is relative to one environment's mutex region, so two environments created the same way hand out the same indices. A thread that held a latch in one environment and took the same-numbered latch in another was reported as a self-deadlock, and the environment panicked.

Who hit it. In a diagnostic build, every replication TCL test panicked at its first election. __rep_update_setup holds the client's rep region latch (mutex 3, rep_backup.c:1112) and sends a message. The test transport's send callback puts the message into a queue database in a second environment, and that put takes the queue environment's mpool region latch, also mutex 3. These are two different latches, so the engine has no bug; the checker was wrong.

Fix. Each held entry records its ENV. The order and same-latch checks compare only entries from the same environment, and release pops only the releasing environment's entry. Release builds compile none of this. The struct is thread-local, so the region signature is unchanged.

Tests (dev box, Debian 12, --enable-diagnostic):

master this branch
lock_order_check, new two-env arm (hold env A's mpool latch, take env B's) BDB2077, SIGABRT PASS
lock_order_check control and lk_partitions=1 arms PASS PASS
rep001 rep002 rep005 rep020 rep021 rep026 rep037 (btree) 7 of 7 panic with BDB2077 7 of 7 PASS

The two-env arm exits with an error if the two indices do not collide, so it cannot pass vacuously.

LTS. mut_order.c, lock_order.h and lock_order_check.c are identical on lts/2026.10.7, so the backport is a clean cherry-pick -x.

… only

A mutex index is relative to one environment's mutex region, so two
environments created the same way hand out the same indices.  The
checker kept one per-thread stack of held indices and compared them
regardless of environment.  A thread that held a latch in one
environment and took the same-numbered latch in another was reported
as a self-deadlock (BDB2077/BDB2080), or as a rank inversion when the
classes differed (BDB2084), and the environment panicked.

The TCL replication harness hits this on every election in an
--enable-diagnostic build.  __rep_update_setup holds mtx_clientdb and
the rep region latch (rep_backup.c:1110-1112) and calls __rep_nextfile,
which sends a message.  The send callback puts it into a queue database
in a second environment, and that put takes the queue environment's
mpool region latch, mutex 3, the same index as the client's rep region
latch.  A non-diagnostic build is clean, and so is the engine: these
are two different latches.

Record the ENV with each held entry.  The order and same-latch checks
compare only entries from the same environment, and release pops only
the entry from the releasing environment.

lock_order_check gains a two-env arm: hold env A's mpool region latch,
take env B's, with an exit if the indices do not collide.  On the dev
box (Debian 12, --enable-diagnostic) master reports BDB2077 and the arm
fails with SIGABRT; with this change it passes, and the control and
lk_partitions=1 arms are unchanged.
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Coccinelle convention checks

No new violations. ✅

Resolved since baseline (3) -- update dist/cocci/baseline.txt to lock these in.
rule_mutex_unbalanced|MUTEX_UNBALANCED|src/btree/bt_curadj.c|return (ret);
rule_mutex_unbalanced|MUTEX_UNBALANCED|src/crypto/mersenne/mt19937db.c|return (ret);
rule_mutex_unbalanced|MUTEX_UNBALANCED|src/mp/mp_register.c|return (ret);

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

ABI diff vs v2026.10.8 (libabigail — authoritative)

abidiff exit bitmask: 0

Removed exported symbols (nm -D, _NNNN version suffix normalized)

None.


Advisory: libabigail/nm is the authoritative binary-ABI check; Coccinelle is complementary source-level early warning. See dist/cocci/README.md.

gburd added 2 commits November 4, 2026 14:37
s_chk_inclconfig requires db_config.h before any other include in a file
that includes it.  Found by the region-signature CI job, whose first step
runs dist/s_validate.
MUTEX_LOCK returns DB_RUNRECOVERY from its caller when the environment is
panicked, so it compiles only inside a function that returns int.  gcc
accepted the void function; clang on FreeBSD rejects it with
-Wreturn-mismatch.
@gburd
gburd marked this pull request as ready for review November 4, 2026 21:55
@gburd
gburd merged commit dc5e6bc into master Nov 4, 2026
63 checks passed
@gburd
gburd deleted the fix/lock-order-per-env branch November 4, 2026 21:55
gburd added a commit that referenced this pull request Nov 4, 2026
lock_order_check.c now includes db_int.h for the two-env arm (#268), and
db_int.h includes dbinc/queue.h from src/.  leak-run.sh builds each driver
with only -I$BUILD, so the leak job failed with "dbinc/queue.h: No such
file or directory" on master after #268 and on the v2026.10.7.3 release
PR.  The Makefile rule already has src/ in CPPFLAGS; this matches it.

Verified on Debian 12 (--enable-debug --enable-diagnostic): every driver
builds and lock_order_check passes all three arms.

(cherry picked from commit 8ba0c85)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant