Skip to content

Commit bcb7bae

Browse files
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

File tree

Cargo.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,8 @@ gitbutler-cherry-pick = { path = "crates/gitbutler-cherry-pick" }
208208
gitbutler-stack = { path = "crates/gitbutler-stack" }
209209
gitbutler-workspace = { path = "crates/gitbutler-workspace" }
210210

211-
# Bundled rusqlite for Windows.
212-
# TODO: is 'bundled' still needed?
213-
rusqlite = { version = "0.38.0", features = ["bundled"] }
211+
# Bundled to ensure a consistent SQLite version across all platforms.
212+
rusqlite = { version = "0.39.0", features = ["bundled"] }
214213
backoff = "0.4.0"
215214
bstr = "1.12.1"
216215
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.

0 commit comments

Comments
 (0)