Skip to content

fix(crons): probe stat -c before stat -f in writeback.sh#34

Open
jdbridgeman wants to merge 1 commit into
crisandrews:mainfrom
jdbridgeman:fix/crons-writeback-stat-portability
Open

fix(crons): probe stat -c before stat -f in writeback.sh#34
jdbridgeman wants to merge 1 commit into
crisandrews:mainfrom
jdbridgeman:fix/crons-writeback-stat-portability

Conversation

@jdbridgeman

Copy link
Copy Markdown

On Linux, _refresh_reconciling_if_fresh crashes the script — which breaks /agent:crons reconcile and the heartbeat's cron repair.

It reads the marker's mtime with stat -f %m first. On GNU coreutils -f means "filesystem status", so that prints a multi-line block to stdout and exits non-zero — the || stat -c %Y fallback then appends the real epoch, leaving marker_mtime as a blob containing the word File. The next line's $((now_s - marker_mtime)) treats File as a variable, and set -u kills the script.

Repro on any Linux host:

touch /tmp/m && stat -f %m /tmp/m   # prints a filesystem block, exits 1

Fix: probe stat -c %Y first (works on GNU, fails clean on BSD/macOS where stat -f %m takes over) — same GNU-first approach already used in _detect_date_flavor. Plus a numeric guard so a bad read can't trip set -u again.

Hit this on WSL2/Ubuntu; reconcile and audit pass after the change.

`_refresh_reconciling_if_fresh` probed the .reconciling marker's mtime with
BSD-style `stat -f %m` first. On GNU coreutils `-f` means "filesystem status",
so `stat -f %m <file>` prints a multi-line filesystem block to stdout and exits
non-zero. The `|| stat -c %Y` fallback then appends the real epoch, leaving
`marker_mtime` as a blob containing the word "File". The arithmetic on the next
line dereferences `File` as a variable and, under `set -u`, exits the whole
script.

This crashes both `audit` and `set-alive` (each calls the helper at its tail,
after the registry write) whenever the marker is present — i.e. during every
`/agent:crons reconcile` and heartbeat cron-repair on a GNU/Linux host
(reproduced on WSL2 / Ubuntu coreutils).

Probe `stat -c %Y` first: it succeeds on GNU and fails cleanly with no stdout on
BSD/macOS, where `stat -f %m` then takes over. Matches the GNU-first,
value-checked convention already used by `_detect_date_flavor`. A numeric guard
is added so any future stat oddity can't re-trip `set -u`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant