Skip to content

seed-prefetch: a paused group is always continued, even after a crash or SIGKILL - #1631

Merged
teamleaderleo merged 5 commits into
mainfrom
fseventsd/governor-always-thaw
Oct 26, 2026
Merged

teamleaderleo merged 5 commits into
mainfrom
fseventsd/governor-always-thaw

Conversation

@teamleaderleo

Copy link
Copy Markdown
Owner

sr2: "SIGCONT before releasing a paused group."

Why

On cosmic-gray (Leo's interactive Mac), several processes niced 5/10 sat stopped (state T) for days. One was pid 40950, a git fsmonitor--daemon on ~/Projects/cmux, stopped since Oct 20. Its FSEvents stream was never drained, and fseventsd likely grew because of it: a 73 GB footprint, 10-14 GB RSS, 60-190% CPU, and a full 50 GB swap. Others: 52713 git ls-files, 89790 git pack-objects, 2784 glaeda-disk. The seed-prefetch Governor is the one glaeda code path that SIGSTOPs a whole process group, and before this change it could leave the group stopped. The attribution is likely, not proven: without root I couldn't trace which process sent the SIGSTOP.

Change (scripts/glaeda-seed-prefetch)

  • Loop death: if a counter raises (read_interface/read_own/job), the Governor's loop ended with the group still stopped until the prefetch timeout (up to 1500 s) or forever. loop() now always continues the group in a finally and marks itself stopped.
  • SIGKILL / crash: before each SIGSTOP the Governor writes a record (STATE/seed-prefetch-paused/<pgid>.json: pgid and the leader's ps lstart), and removes it after the SIGCONT. Every prefetch run first calls thaw_left_paused, which SIGCONTs any group a dead run left recorded, but only while the leader is the same process (same pid and same start time), so a reused pid is never signalled. If no record can be written, no pause is taken.
  • stop() goes through the same resume() and doesn't join its own thread.

Audit of other SIGSTOP users

  • scripts/glaeda-cmux-runner-hook ListenerGate.stop: it already SIGCONTs every frozen pid in a finally on every return and exception path. Only a SIGKILL between the STOP and the CONT (milliseconds) could leave it frozen. Not changed here.
  • scripts/benchmark-linker-throughput: it stops itself and its parent continues it (benchmark only). Not changed.

Tests

Four new tests in scripts/test-glaeda-seed-prefetch.py: a raising counter never leaves the group stopped; a pause is recorded and a later run continues a group a killed run left; a reused pid or a bad record is never signalled; no record means no pause. The full suite (53 tests) passed on huge-blue. pr-overlap: no open PR overlaps (I checked the disk-glaeda stack #1622-#1626, which doesn't touch seed-prefetch).

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 26, 2026 16:11
… or SIGKILL

The Governor SIGSTOPs the prefetch's process group while a job downloads. stop() continued it,
but a counter that raised ended the loop with the group still stopped, and a SIGKILLed run
(launchd, OOM, power) left it stopped forever. Now the loop's end continues the group; each
pause is recorded (pgid plus the leader's start time) before the SIGSTOP and dropped after the
SIGCONT; and every run first continues any group a dead run left recorded, only while its leader
is the same process. With no record, no pause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-85ca59f74f02d81734c3
@teamleaderleo

Copy link
Copy Markdown
Owner Author

Owned by an agent session · session

teamleaderleo and others added 3 commits October 26, 2026 16:25
…ot settle, no ps under the Governor lock

Review (Codex): thaw ran only inside prefetch(), outside the lock, dropped records on a ps or
SIGCONT failure, ran ps without a timeout under the Governor's lock, and missed a group whose
leader exited. Now run() thaws first under the prefetch lock on every run (records live in its
work folder); a group whose leader exited is continued while members live; ps has a timeout and
runs once outside the lock; a record stays when ps cannot tell or SIGCONT fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-85ca59f74f02d81734c3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-85ca59f74f02d81734c3
…SIGCONT keeps the record

Review (Codex): ps lstart has one-second precision, and resume() treated any SIGCONT error as
success and dropped the record. Now leader_start reads proc_pidinfo (macOS, sec.usec) or /proc
starttime with the boot id (Linux), and the record and pause stay unless SIGCONT succeeded or
the group is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-85ca59f74f02d81734c3
@teamleaderleo
teamleaderleo merged commit 81c825e into main Oct 26, 2026
16 checks passed
@teamleaderleo
teamleaderleo deleted the fseventsd/governor-always-thaw branch October 26, 2026 23:50
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