Commit Graph

3 Commits

Author SHA1 Message Date
joaomarcos 80e4fb5995 fix(gateway): reap only the background processes an abandoned turn created
An agent turn can spawn a long-running background subprocess (e.g.
`next build`) and later be abandoned via inactivity timeout, /stop,
/new, or a client disconnect. Before this fix the gateway interrupted
the agent loop but never touched the subprocess: it kept running
inside the gateway's cgroup, unbounded, until memory pressure starved
the event loop and made every platform/cron look hung (#76115).

The process registry already knew how to kill a process tree — the
missing piece was per-turn ownership: nothing distinguished a process
that predates the turn (must survive), a process the turn started and
finished successfully (must survive), and a process an abandoned turn
left running (must be reaped).

- tools/process_registry.py: snapshot_running_ids() captures a turn's
  starting baseline; kill_started_since() reaps only IDs created after
  it, scoped to one task_id.
- gateway/turn_context.py: TurnContext carries process_task_id +
  process_baseline so the timeout/interrupt paths can reach them.
- gateway/run.py: baseline is snapshotted right before the turn's
  executor task starts; the inactivity-timeout path and the explicit
  /stop|/new|disconnect interrupt path both reap via the same helper.
  A daemon-thread watchdog backs up the asyncio-based timeout poll,
  since a starved event loop is exactly the failure mode this bug
  causes. The turn's own worker clears its ownership markers the
  instant it finishes, closing a race where a /stop landing right
  after normal completion could reap a background process the turn
  deliberately left running.

Related but insufficient on their own: #37454 (cgroup ExecStopPost
reaper only fires on service restart) and #68915 (orphaned-pipe
grandchild detection, a registry bug not a turn-lifecycle gap).
Neither ties process cleanup to turn abandonment.
2026-08-02 14:23:55 +05:30
teknium1 1a3a9de630 refactor(gateway): extract run_sync onto TurnRunner (completes the TurnContext seam; AST-identical body) 2026-07-29 16:21:46 -07:00
teknium1 a022229566 refactor(gateway): TurnContext/TurnRunner seam — extract _run_agent_inner nested closures (byte-identical bodies) 2026-07-29 13:34:03 -07:00