on main help sign in
chore(db): log lock metadata write failures and explain lock file lifetime

Address review feedback on the data directory lock. The metadata written into the lock file is informational only, but silently swallowing a write failure leaves a future contender with no clues to report. Log it at debug level. Also leave a comment next to the lock acquisition explaining why we intentionally do not delete the lock file on release: flock is keyed by inode, and any close-then-unlink ordering opens a race where two processes can each hold a flock on a different inode that lives at the same path. Co-Authored-By: Charm Crush <crush@charm.land>

commit3c981c192fd23879a2e8531391e0971b3d1ecfd0 authorChristian Rocha <christian@rocha.is> dateTue 19 May 2026, 21:32 (5 months ago) parent6923820
1 file changed+9−4
internal/db/datadirlock.go+9−4
internal/db/datadirlock.go+9−4
@@ -4,6 +4,7 @@ import (
44 "encoding/json"
55 "errors"
66 "fmt"
7+ "log/slog"
78 "os"
89 "path/filepath"
910 "strconv"
@@ -63,13 +64,17 @@ func acquireDataDirLock(dataDir string) (*dataDirLock, error) {
6364 // Record ownership metadata so a contending process can identify
6465 // us. Failures here are non-fatal: the OS-level lock is what
6566 // actually guarantees mutual exclusion, and a missing/partial JSON
66− // payload only degrades diagnostics.
67+ // payload only degrades the diagnostic a contender prints.
6768 if err := writeOwnerInfo(path); err != nil {
68− // Best-effort; log via stderr only when running in a debug
69− // context would be invasive here, so we silently swallow.
70− _ = err
69+ slog.Debug("Failed to write data-dir owner info", "path", path, "error", err)
7170 }
7271
72+ // The lock file itself is intentionally never unlinked. flock is
73+ // keyed by inode, not by path, and any close-then-unlink (or
74+ // unlink-then-close) ordering opens a window where two processes
75+ // can each hold a flock on a different inode that lives at the
76+ // same path. Leaving the file in place lets every acquirer see
77+ // the same inode and lets the kernel arbitrate correctly.
7378 return &dataDirLock{release: release}, nil
7479}
7580