Summary & Motivation
Worker adapters frequently spawn external tool processes, compilers, test runners (pytest, npm test, cargo build), or language servers. If a contract times out or is aborted via Ctrl+C / SIGINT, child and grandchild processes can detach and become runaway orphans consuming 100% CPU in the background.
While orchestrator/verifier.py contains basic process termination, we need a unified, resilient Cross-Platform Process-Tree Orphan Sweeper across all worker adapters.
Proposed Solution
- Unified Process Tracker (
orchestrator/process_guard.py):
- Windows: Uses Job Objects (
CreateJobObject, AssignProcessToJobObject) with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. When the parent handle closes, Windows OS kernel automatically terminates all descendants atomically.
- POSIX (macOS / Linux): Uses process group leadership (
os.setpgrp() / preexec_fn=os.setsid) paired with os.killpg(pgid, signal.SIGKILL).
- Signal Trap & Cleanup Registry:
- Maintains an in-memory process registry.
- Registers
atexit and signal.signal handlers (SIGINT, SIGTERM, SIGHUP) to execute immediate sweep before exit.
Acceptance Criteria
Summary & Motivation
Worker adapters frequently spawn external tool processes, compilers, test runners (
pytest,npm test,cargo build), or language servers. If a contract times out or is aborted viaCtrl+C/SIGINT, child and grandchild processes can detach and become runaway orphans consuming 100% CPU in the background.While
orchestrator/verifier.pycontains basic process termination, we need a unified, resilient Cross-Platform Process-Tree Orphan Sweeper across all worker adapters.Proposed Solution
orchestrator/process_guard.py):CreateJobObject,AssignProcessToJobObject) withJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. When the parent handle closes, Windows OS kernel automatically terminates all descendants atomically.os.setpgrp()/preexec_fn=os.setsid) paired withos.killpg(pgid, signal.SIGKILL).atexitandsignal.signalhandlers (SIGINT,SIGTERM,SIGHUP) to execute immediate sweep before exit.Acceptance Criteria
Ctrl+Cduring a running loop terminates all spawned subprocesses immediately with 0 orphan processes left behind.