mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-15 09:25:28 +02:00
fix: adversarial-review runtime fixes across the telemetry + kill paths
- session-runner: exit-labeling keys off 'exit', not 'close' — an orphan holding the pipes could relabel a REAL exit (auth failure) as 'timeout_startup' availability noise; the kill path still always group-kills and cancels the reader (labeling and unblocking are separate concerns). Work phase arms on a flag, not firstResponseMs===0 (a same-ms first byte left the startup timer live all run). The CI startup grace is now a real FLOOR (Math.max), matching its name and pinning test. - gstack-detach: pgid captured AT SPAWN (== child pid under start_new_session) — resolving it after the grace raised ESRCH once the leader died on SIGTERM, orphaning TERM-immune grandchildren forever. - test-free-shards: ledger entries carry branch + git_sha (rev-parse split: '--abbrev-ref HEAD HEAD' printed the branch twice and recorded it as the sha); local ledger default is per-PROJECT, not the machine-global tmpdir. - eval-flake-rank: per-LINE ledger parse (one torn JSONL line vanished the whole series), 60-day recency bound (transcript-bearing files are MBs), shared isFinalizedEvalResultFile predicate (the artifact-taxonomy rule lived in three places); eval-store exports the predicate and finalize stops computing flakyRetries twice; paid-shards cleanup uses async rm (a SIGKILLed shard's git-workspace teardown blocked every sibling's stream classification on the parent event loop). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5b04f05ba4
commit
513111a166
+10
-3
@@ -96,13 +96,19 @@ def child_run(args, log):
|
||||
proc = subprocess.Popen(
|
||||
cmd, stdout=f, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL, start_new_session=True
|
||||
)
|
||||
# Capture the PGID AT SPAWN (== proc.pid: start_new_session makes the
|
||||
# child a session/group leader). Resolving it later via
|
||||
# os.getpgid(proc.pid) raises ESRCH once the leader exits — a leader
|
||||
# that died on the SIGTERM while a TERM-immune grandchild survived
|
||||
# left that grandchild alive forever (codex adversarial finding).
|
||||
pgid = proc.pid
|
||||
if args.timeout and args.timeout > 0:
|
||||
try:
|
||||
code = proc.wait(timeout=args.timeout)
|
||||
except subprocess.TimeoutExpired:
|
||||
log_line(log, f"### gstack-detach WATCHDOG fired after {args.timeout}s — killing ### {_now()}")
|
||||
try:
|
||||
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||
os.killpg(pgid, signal.SIGTERM)
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(5)
|
||||
@@ -110,9 +116,10 @@ def child_run(args, log):
|
||||
# eval runs spawn claude/codex grandchildren that survive a
|
||||
# proc.kill() and burn cores + API for hours (the observed
|
||||
# 15-hour-orphan class). ESRCH here just means the group
|
||||
# honored the SIGTERM.
|
||||
# honored the SIGTERM. Uses the SAVED pgid so a dead leader
|
||||
# cannot orphan its group.
|
||||
try:
|
||||
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
|
||||
os.killpg(pgid, signal.SIGKILL)
|
||||
except Exception:
|
||||
try:
|
||||
proc.kill()
|
||||
|
||||
Reference in New Issue
Block a user