mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-21 15:51:30 +02:00
aborting_on binds one stage's abort check for the whole worker process, but only stream_json consulted it. CLIToolRunner.run was a blocking subprocess.run, so nine tool paths ran to their own budget after a cancel or a pause: naabu under host_discovery for up to an hour, ffuf per IP for thirty minutes, wafw00f, urlfinder, alterx, cdncheck, dnsx and every subdomain provider for theirs. revoke_scan_tasks deliberately does not terminate, so nothing else was going to stop them. run() now waits in poll-sized slices and raises StageAbortedError, which moves to tools/runner/abort.py so a tool raises the same class the orchestrator already catches. A finished tool still returns immediately: the wait is proc.wait(timeout=slice), not a sleep. Killing the direct child was not enough either. A tool that forks leaves a grandchild holding the pipes, which keeps hitting the target and blocks the reader threads until their join times out — twelve seconds to stop a sleep in the test that found it. Every tool now starts in its own process group and is stopped with killpg, on both paths. stdin moves to its own thread beside the readers so a tool that never reads it cannot deadlock the write. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X5roHYDYzSPRNaTkn8hSkJ