Commit bcb7bae
committed
fix: update rusqlite to 0.39.0 to resolve SQLite WAL deadlock
While investigating a deadlocked but-server instance, we identified an
ABBA lock-order inversion in SQLite 3.51.1's Unix VFS between two
internal mutexes:
- `unixBigLock` (a global static mutex, alias SQLITE_MUTEX_STATIC_VFS1)
- per-inode `pLockMutex` (heap-allocated per open database file)
The documented invariant in os_unix.c requires that unixBigLock is
always acquired before pLockMutex, but `unixIsSharingShmNode()` violated
this by acquiring pLockMutex first and then calling `unixEnterMutex()`
(which acquires unixBigLock). This path is exercised during WAL close
(`sqlite3WalClose` → `sqlite3OsLock(EXCLUSIVE)` → `unixLock` →
`unixIsSharingShmNode`), which `but-db` triggers because it enables WAL
mode via `PRAGMA journal_mode = WAL` and opens a fresh connection per
request.
Under concurrent open/close on the same database file the two threads
deadlock:
Thread A: unixClose() — holds unixBigLock, waits for pLockMutex
Thread B: unixLock() via WAL — holds pLockMutex, waits for unixBigLock
The cascade effect: threads holding a `RepoExclusiveGuard` (RwLock write)
cannot complete, causing the global `WORKTREE_LOCKS` mutex in
`but-core/src/sync.rs` to be held indefinitely, which blocks all
subsequent `shared_repo_access`/`exclusive_repo_access` calls process-wide.
The bug was fixed by the SQLite project in commit 67767084b6
(sqlite/sqlite@6776708,
December 2025) — released as SQLite 3.51.2 — by removing the
`unixEnterMutex()`/`unixLeaveMutex()` calls from `unixIsSharingShmNode()`.
rusqlite picked up the fix in PR #1788 (merged 2026-01-13), shipping
libsqlite3-sys 0.37.0 with SQLite 3.51.3 as part of rusqlite 0.39.0.
This commit bumps rusqlite from 0.38.0 (SQLite 3.51.1, broken) to 0.39.0
(SQLite 3.51.3, fixed).1 parent e718c96 commit bcb7bae
2 files changed
Lines changed: 19 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
212 | | - | |
213 | | - | |
| 211 | + | |
| 212 | + | |
214 | 213 | | |
215 | 214 | | |
216 | 215 | | |
| |||
0 commit comments