Files
stack/agents/researcher/work/queue-71/r1/run_group.py
T
jason.woltjeandClaude Opus 5.5 471f5cf202 researcher: row 71 round 1 packet on ac6b56ee, tasks 89/0, bus 115/0, mutants killed (#1565)
Haiku subagent build under decision 129. Candidate manifest 9ac3a56e
names packages/tasks/src/fake.mjs and packages/tasks/tests/tree.test.mjs.
Gate and both named mutants ran in Sage's slot.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 09:50:00 -05:00

56 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""Run one command in its own session and process group, with a timeout.
usage: run_group.py TIMEOUT_S LOGFILE CWD -- CMD [ARGS...]
Child stdout and stderr go to LOGFILE. On timeout the whole process group gets
SIGTERM, then SIGKILL after 5 s. After the child exits, anything still left in
its group is killed too, so nothing from one step outlives it.
Exit status: the child's, or 124 on timeout.
"""
import os
import signal
import subprocess
import sys
def group_kill(pgid, sig):
try:
os.killpg(pgid, sig)
except ProcessLookupError:
pass
def main():
timeout = float(sys.argv[1])
log = sys.argv[2]
cwd = sys.argv[3]
cmd = sys.argv[sys.argv.index('--') + 1:]
with open(log, 'w') as out:
p = subprocess.Popen(
cmd,
cwd=cwd,
stdout=out,
stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL,
start_new_session=True,
)
try:
rc = p.wait(timeout=timeout)
except subprocess.TimeoutExpired:
group_kill(p.pid, signal.SIGTERM)
try:
p.wait(timeout=5)
except subprocess.TimeoutExpired:
pass
group_kill(p.pid, signal.SIGKILL)
p.wait()
out.write(f"\nTIMEOUT after {timeout:.0f}s: process group {p.pid} killed\n")
rc = 124
group_kill(p.pid, signal.SIGKILL)
sys.exit(rc)
if __name__ == '__main__':
main()