fix(wake-lib): derive Linux pid identity from /proc ticks, not ps lstart#392
Open
iiiwulatam-blip wants to merge 3 commits into
Open
fix(wake-lib): derive Linux pid identity from /proc ticks, not ps lstart#392iiiwulatam-blip wants to merge 3 commits into
iiiwulatam-blip wants to merge 3 commits into
Conversation
ps -o lstart= renders from /proc/stat's btime plus starttime ticks, and btime shifts whenever the wall clock is stepped (settimeofday). On WSL2 the guest clock steps repeatedly after boot, so a watcher's recorded pid identity drifted out of sync with a fresh read for the same still-running process, and fm_watcher_lock_matches_pid wrongly rejected a healthy watcher as dead. On Linux, fm_pid_identity now reads /proc/<pid>/stat field 22 (starttime, in clock ticks since boot) combined with the process command line from /proc/<pid>/cmdline - both immune to wall-clock steps. Non-Linux platforms keep the previous ps lstart-based identity unchanged as a fallback. The identity is an opaque string; a lock written under the old format reads as unhealthy once and self-heals on the next arm/restart. Tests added to tests/fm-watcher-lock.test.sh cover: identity stability across consecutive reads, distinctness across processes, fm_watcher_lock_matches_pid accept/reject, and that the Linux identity is ticks-derived rather than a rendered wall-clock date. The actual clock-step regression cannot be reproduced in a unit test (the system clock can't be stepped in-test); these are the honest unit-level proxies for it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fm_pid_identityinbin/fm-wake-lib.shusedps -o lstart=to build the opaque identity string thatfm_watcher_lock_matches_pidcompares against a recorded watcher/daemon lock.ps -o lstart=renders from/proc/<pid>/stat'sstarttimecombined with the kernel's boot time (/proc/stat'sbtime), andbtimeshifts whenever the wall clock is stepped (settimeofday). On WSL2 the guest clock steps repeatedly after boot, so a watcher's recorded identity drifted out of sync with a fresh read of the same still-running process, andfm_watcher_lock_matches_pidwrongly rejected a healthy, still-running watcher as dead.On Linux,
fm_pid_identitynow reads/proc/<pid>/statfield 22 (starttime, in clock ticks since boot) combined with the process command line from/proc/<pid>/cmdline- both immune to wall-clock steps. Non-Linux platforms (Darwin) keep the previousps -o lstart= -o command=identity unchanged as a fallback, since/procis Linux-only.The identity is treated as an opaque string throughout the codebase, so this is a compatible format change: a lock written under the old
ps lstart-based format reads as unhealthy exactly once (the first health check after upgrade) and self-heals on the next arm/restart, the same recovery path already used for any other stale-lock case.Four tests were added to
tests/fm-watcher-lock.test.sh:fm_watcher_lock_matches_pidaccept/reject behaviorThe actual clock-step regression cannot be reproduced in a unit test (the system clock can't be stepped in-test); these are the honest unit-level proxies for it.
This PR's head also includes two commits produced by this repo's own
no-mistakesvalidation pipeline during the run described below: a test-fixture stabilization commit (unrelated flaky/environment-sensitive assertions intests/fm-bootstrap.test.shandtests/fm-dispatch-select.test.sh) and a documentation-sync commit (docs/architecture.md,docs/scripts.md,docs/turnend-guard.md,.agents/skills/afk/SKILL.md) describing the new Linux PID-identity behavior. Both are included because the pipeline run below validated this exact head.Evidence: no-mistakes pipeline run
This branch was validated end-to-end through this repo's own
no-mistakesgate (rebase, review, test, document, lint), with 0 findings at every step, run id01KX4GV98W8TMP50HJ1HJKJ91G, resulting head4a0fa47d. Only the pipeline's ownpushstep failed, with a plain permissions error against the upstreamoriginremote (the authenticated account backing this task has no write access there and no pre-existing fork). That push failure is a credentials/target issue, not a finding about the code, so this run stands as the validation evidence for the head pushed here; this PR was opened manually (push to a fork, then this PR) as the documented fallback.Test plan
shellcheck bin/fm-wake-lib.sh- cleanbash tests/fm-watcher-lock.test.sh- all tests pass (27/27, including the 4 new ones)bash tests/fm-turnend-guard.test.sh- all tests pass, no regressions (format-agnostic consumer offm_pid_identity)bash tests/fm-daemon.test.sh- all tests pass, no regressions (format-agnostic consumer)no-mistakespipeline (rebase/review/test/document/lint) - 0 findings, see evidence section above