Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs real behavior proof before merge. Reviewed September 18, 2026, 1:58 PM ET / 17:58 UTC (Revision 5). ClawSweeper reviewWhat this changesAdds a 15-second deadline to OCM’s once-only supervisor execution, reuses process-group shutdown on timeout, and adds three Unix tests. Merge readiness⛔ Blocked before merge - 6 items remain The prior descendant-cleanup finding is addressed, and neither current main nor v0.2.47 implements the timeout. The new unconditional deadline still changes existing behavior, and production-command proof remains incomplete. Priority: P2 Review scores
Verification
How this fits togetherOCM’s supervisor loads saved environment service plans and launches their gateway processes under admission locks. Once-only execution waits for each child and returns its result; this change introduces timeout termination. flowchart TD
A[Once-only command] --> B[Saved service plan]
B --> C[Admission checks and lock]
C --> D[Spawn gateway process group]
D --> E{Child exits within deadline?}
E -->|Yes| F[Record result and continue]
E -->|No| G[Terminate group and return error]
Decision needed
Why: The cutoff cannot distinguish a wedged child from a healthy gateway, and the contributor explicitly leaves this behavior choice unresolved. Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Preserve existing wait behavior by default and make bounded diagnostic execution explicit, with owner-approved semantics and fresh-plan and upgrade proof. Do we have a high-confidence way to reproduce the issue? Yes, from source: a saved-plan child that completes after 20 seconds succeeds under the existing wait but is terminated by this patch after 15 seconds. No runtime reproduction or artifact-producing checks were executed during this read-only review. Is this the best way to solve the issue? No, the unconditional cutoff is not yet a safe compatibility choice; reusing group cleanup is sound, but an explicit diagnostic deadline preserves existing behavior. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 6ff9fb59f105. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (4 earlier review cycles)
|
ocm service --once blocked forever on child.wait() if an env child never exited. Wait with a deadline and kill the child on timeout, matching the handoff wait helper. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> (cherry picked from commit 40ce43f)
The 200ms deadline plus SIGTERM grace can exceed 1s on macos-latest. Keep proving we do not wait the full 30s sleep. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> (cherry picked from commit c85f0e6)
c85f0e6 to
d9e51cb
Compare
dev_stop_acknowledgement_refuses_live_recorded_ownership failed once on macos-latest; the same test passed on openclaw#117 and openclaw#136 from the same main. This PR does not touch that test. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
terminate_child returned when the group leader exited after TERM, so a SIGTERM-ignoring grandchild stayed alive after run_once released admission. Reuse the existing process-group shutdown used by stop_supervisor_child. The 15s once-mode default is unchanged. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
@clawsweeper re-review P2 wait-for-process-group-cleanup is in the tip.
Live analog:
Owner decision still needed: should |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Thanks for improving the process-group cleanup. I’m closing this version because An explicit diagnostic timeout would be a separate capability. This maintenance pass will preserve the existing once-mode lifetime contract. |
What Problem This Solves
Fixes an issue where
ocm service --once(the__daemon run --oncepath) would hang forever when a planned env child never exited. After spawn,run_oncecalledchild.wait()with no deadline.On timeout, the first waiter sent TERM to the process group, then returned as soon as the group leader exited. A descendant that ignores SIGTERM stayed alive after
run_oncereturned and released admission.On origin/main the hang is here:
ocm/src/supervisor/mod.rs
Lines 809 to 811 in e04c101
e04c101
This is separate from PR #136, which bounds git worktree helpers.
Why This Change Was Made
run_oncenow waits throughwait_child_with_timeout. The child is polled, then terminated whenSERVICE_ONCE_CHILD_TIMEOUT_MS(15s) expires. Timeout cleanup now reuses the existing group-aware supervisor shutdown: wait for live process-group members, then KILL, then reap the leader. Long-runningrun_until_stoppedis unchanged. The 15s once-mode default is unchanged.User Impact
A stuck env child in once-mode fails after 15s instead of hanging
ocm service --once. A TERM-resistant leftover in that group is killed before admission is released. Children that exit on their own still report their exit status.Evidence
Live analog: a grandchild ignores SIGTERM. TERM alone leaves it alive. KILL removes it.
The patched
wait_child_with_timeoutruns that same shape (leader sleeps, descendant ignores TERM) with an 800ms deadline. It returns a timeout error and the descendant is gone. The 15s production default is unchanged.Earlier rustc
/bin/sleep 30vs naivechild.wait()remains: naive still running after 1006ms, timed waiter returns at 200ms and the sleep pid is gone.Real behavior proof
ocm service --onceno longer blocks forever onchild.wait(). After the 15s deadline, the waiter kills the process group, including a descendant that ignored SIGTERM, then returns an error./private/tmp/ocm137-p2onfix/supervisor-run-once-timeout.python3 /tmp/proof-ocm136-p2-live.py. Then ran the patchedwait_child_with_timeoutagainstperlthat forks a SIGTERM-ignoring child, writes its pid, and sleeps 30s, with an 800ms deadline.alive_after_term_only=True,gone_after_kill=True. The patched waiter returned a timeout in 1.93s with the descendant gone.SERVICE_ONCE_CHILD_TIMEOUT_MSis still 15000.stop_supervisor_child. A SIG_IGN leftover is gone after the waiter returns. A child that exits on its own still reports success. The 15s default is unchanged.__daemon run --onceagainst a saved plan and admission lock, a launchd/systemd install, and the Windows job-object kill path. Whether once-mode should keep a hard 15s default is an owner decision.Summary
Bounded
run_oncechild wait. Timeout cleanup reuses the existing supervisor process-group shutdown. 15s default unchanged.