fix(settings-hook): GNU-first stat in the lock stale check — Linux abort on held locks

On Linux, BSD-style `stat -f %m` prints a multi-line FILESYSTEM block to
stdout before exiting 1, so the BSD-first || chain captured that garbage
concatenated with the real `stat -c %Y` epoch. The non-numeric mtime made
`$(( now - mtime ))` a syntax error and set -e killed the binary with
exit 1 whenever a lock dir already existed — every contention path (stale
takeover, give-up, concurrent writers) broke on CI while staying green on
macOS, where BSD stat -f succeeds cleanly.

GNU `stat -c %Y` now goes first (BSD stat rejects -c with no stdout, so
macOS falls through cleanly), and a numeric guard blanks any residual
garbage so a future platform quirk degrades to the normal give-up path
instead of an arithmetic abort. Same defect class as gstack-repo-mode's
GNU-first ordering (#2195). Verified in an oven/bun Linux container:
the four CI-failing lock tests now pass (62/62 across both files).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-18 16:46:15 -07:00
co-authored by Claude Fable 5
parent b56f8a508c
commit f46e321ab4
+8 -1
View File
@@ -265,7 +265,14 @@ _acquire_lock() {
fi
# Stale takeover: atomic rename means exactly one contender wins; the
# loser loops and re-contends against the winner's fresh mkdir.
mtime=$(stat -f %m "$_LOCK_DIR" 2>/dev/null || stat -c %Y "$_LOCK_DIR" 2>/dev/null || echo "")
# GNU stat (-c %Y) first: on Linux, BSD-style `stat -f %m` prints a
# multi-line FILESYSTEM block to stdout before failing, and the || chain
# would capture that garbage alongside the real epoch. BSD stat rejects
# -c with no stdout, so macOS falls through cleanly. The numeric guard
# below makes any residual garbage inert (no takeover, normal give-up)
# instead of an arithmetic abort under set -e.
mtime=$(stat -c %Y "$_LOCK_DIR" 2>/dev/null || stat -f %m "$_LOCK_DIR" 2>/dev/null || echo "")
case "$mtime" in *[!0-9]*) mtime="" ;; esac
now=$(date +%s)
if [ -n "$mtime" ] && [ $(( now - mtime )) -gt "$stale_after_s" ]; then
stale="$_LOCK_DIR.stale.$$-$RANDOM"