fix(tui): reschedule WS orphan reap while a turn is still running - #85598
fix(tui): reschedule WS orphan reap while a turn is still running#85598686f6c61 wants to merge 1 commit into
Conversation
The grace timer treated mid-turn detached sessions as not-orphaned and returned without arming another timer. Eviction paths also skip running sessions, so the in-memory agent leaked until process restart. Fixes NousResearch#85578
Duplicate of #44102: the same detached mid-turn WS orphan-reap timer is re-armed so the session can be reaped after the turn finishes. |
|
Same bug as open #44102 (fixes #44045) — mid-turn detached sessions spare the one-shot grace timer and never get a second look. #44102 is the earlier write-up; it is now This tip is that re-arm, folded into the existing |
fix(tui): reschedule WS orphan reap while a turn is still running
|
|
@C:/Users/admin/AppData/Local/Temp/opencode/review-85598.md |
What breaks
Desktop / TUI: disconnect while a turn is still running. The session stays in
_sessionsforever (ended_atNULL, no error). The in-memory agent is never released. Seen on v0.20.0, Linux/Docker. Config timeouts (gateway_timeout,session_stall_timeout,max_live_sessions) do not help — every eviction path skipsrunning.This is an eighth leak next to the family in #84047 (closest is F, but distinct).
Why
handle_wsdetach points the session at_detached_ws_transportand arms onethreading.Timer(_schedule_ws_orphan_reap, default 20s)._ws_session_is_orphaned()is:If the timer fires mid-turn,
_reap()hitsnot orphanedand returns. The active-delegation branch one line below correctly calls_schedule_ws_orphan_reapagain; the running branch did not. After that, nothing re-arms the timer. The 6h TTL reaper also treatsrunningas non-evictable. If the turn never clears from the leak’s point of view, the session is immortal.What this changes
A detached session that is still
runningreschedules the same grace timer (same as delegations). When the turn later clears, the next fire sees a real orphan and tears down.Live transports and finalized sessions still return immediately (no reschedule loop).
Verify
Fake Timer, session starts
running=True+ detached transport: first fire keeps it and arms again; afterrunning=False, second fire teardowns withws_orphan_reap.Fixes #85578