eleven / messenger Public

registry: set busy_timeout before journal_mode=WAL (#1239)

journal_mode=WAL takes a lock, and with no busy_timeout applied yet, two
processes opening the registry at once (the router starting while
add-instance or the tunnel gateway runs) can fail immediately with
SQLITE_BUSY instead of waiting their turn. Order the pragmas so the
timeout is in place before WAL.

Found while porting the router for titogo, which has carried this fix since.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 8ab43ab880db8d4e394a0c47cc3e8380dc6ac84e parent a86c5fb
1 file changed, +5 −1
  • registry.go +5 −1
diff --git a/registry.go b/registry.go
index a19371a..d288175 100644
--- a/registry.go
+++ b/registry.go
@@ -112,9 +112,13 @@ func openRegistry(path string) (*Registry, error) {
}
// One writer at a time keeps WAL happy (mirrors openDB).
d.SetMaxOpenConns(1)
+ // busy_timeout FIRST: two processes open this DB concurrently (the router
+ // starting while add-instance or the tunnel gateway runs), and
+ // journal_mode=WAL takes a lock — with no timeout set yet the loser fails
+ // immediately with SQLITE_BUSY instead of waiting its turn.
for _, p := range []string{
- "PRAGMA journal_mode=WAL",
"PRAGMA busy_timeout=5000",
+ "PRAGMA journal_mode=WAL",
"PRAGMA synchronous=NORMAL",
} {
if _, err := d.Exec(p); err != nil {