fix(slopmachine): bound verification process cleanup - #124
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
There was a problem hiding this comment.
🟡 Changes recommended
The new runShell implementation introduces platform-compilation gaps (non-linux/darwin) and has a cancellation/grace-period edge case that should be corrected.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR tightens slopmachine verify --cmd process management to prevent hangs when descendants keep inherited output pipes open, while ensuring the owned process group is terminated and cleanup is bounded.
Changes:
- Reworked
runShellcleanup to observe shell exit without immediately reaping it, then terminate remaining process-group members and bound pipe draining. - Added Linux/Darwin-specific primitives for “leader exited but not reaped yet” detection and cleanup error handling, plus new regression tests for pipe-hold and process-group cleanup behavior.
- Updated agent interface documentation and adjusted verification exit-code handling on errors vs cancellations.
File summaries
| File | Description |
|---|---|
| cli/slopmachine/go.mod | Promotes golang.org/x/sys to a direct dependency for new OS-specific process primitives. |
| cli/slopmachine/docs/AGENT_INTERFACE.md | Documents the new process-group ownership, cancellation grace, and pipe-drain bounds. |
| cli/slopmachine/cmd/slopmachine/process_test.go | Adds cross-test helpers and regression tests for pipe-hold hangs and termination state assertions. |
| cli/slopmachine/cmd/slopmachine/process_linux.go | Adds Linux waitForExit implementation using waitid(WNOWAIT) and cleanup-error policy stub. |
| cli/slopmachine/cmd/slopmachine/process_linux_test.go | Implements Linux zombie detection via /proc/<pid>/stat for termination-state tests. |
| cli/slopmachine/cmd/slopmachine/process_darwin.go | Adds Darwin kqueue-based exit observation and logic to optionally ignore EPERM after safe exit. |
| cli/slopmachine/cmd/slopmachine/process_darwin_test.go | Adds Darwin regression test ensuring EPERM isn’t ignored for a live leader. |
| cli/slopmachine/cmd/slopmachine/main.go | Updates cancellation exit codes and reworks runShell cleanup/termination flow with bounded drain. |
| cli/slopmachine/cmd/slopmachine/main_test.go | Updates cancellation process-group test to assert termination of all expected descendants. |
Review details
Suppressed comments (1)
cli/slopmachine/cmd/slopmachine/main.go:1812
- Cancellation detection is based only on
watchErr. Ifctxis canceled afterwaitForExitobserves shell exit (e.g., during pipe draining),cancelledstays false so the code skips the SIGTERM+500ms grace but still returns cancellation (viactx.Err() != nil). Consider treatingctx.Err() != nilas cancellation up front so cancellation always follows the documented TERM grace period.
watchErr := waitForExit(ctx, pid)
cancelled := errors.Is(watchErr, context.Canceled) || errors.Is(watchErr, context.DeadlineExceeded)
var cleanupErr error
- Files reviewed: 9/9 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Problem
Verification can hang after its shell exits when a descendant keeps an output pipe open. Cancellation can also wait indefinitely for escaped helpers, while normal exit can leave members of the owned process group running.
Solution
Observe shell exit without reaping its PID until process-group cleanup finishes. Preserve the 500 ms TERM grace on cancellation, terminate remaining owned members, and bound inherited-pipe draining to two seconds. Preserve shell exit codes and output digests; incomplete draining fails verification. Helpers that create a separate session remain outside the owned group.
Proof
Detached-pipe fixtures failed against the original implementation at five seconds for both normal completion and cancellation. Darwin process regressions now pass, covering normal group cleanup, graceful TERM handling, output digests and refusal to suppress permission errors for a live leader. Tests distinguish a live child from an unreaped zombie and a reaped child; cancellation asserts every member of a finite three-process group. The full slopmachine owner gate passed locally with race detection, CLI coverage 80.2% and integration coverage 76.4%. Linux process proof runs in PR CI before merge.
Independent slopguard review of the final target is clean. The earlier Linux zombie-state assertion finding was corrected and reviewed again.
Regression evidence (original implementation):