-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Severity: High
Category: Memory Leak
File: src/web/server.ts
Description
When a PTY process exits, the exit event handler (line 4711) broadcasts the event and cleans up the respawn controller and timer. It does not remove the session from this.sessions, does not remove its listener closures from this.sessionListenerRefs, and does not clean up associated resources like runSummaryTrackers, subagentWatchers, or transcriptWatchers.
Code
src/web/server.ts:4711–4738:
exit: (code) => {
// broadcasts...
// cleans respawn controller ✓
const controller = this.respawnControllers.get(session.id);
if (controller) { controller.stop(); ... this.respawnControllers.delete(session.id); }
// cleans respawn timer ✓
const timerInfo = this.respawnTimers.get(session.id);
if (timerInfo) { clearTimeout(timerInfo.timer); ... }
// nothing below:
// ✗ this.sessions still holds the session
// ✗ this.sessionListenerRefs still holds listener closures
// ✗ this.runSummaryTrackers not cleaned
// ✗ subagentWatchers / transcriptWatchers not cleaned
},cleanupSession() handles all of this correctly — but it is only triggered by explicit user deletion or certain error paths, not by natural PTY exit.
Impact
sessionListenerRefs holds closures that capture the full Session object (including up to 2MB terminal buffer). For short-lived auto-sessions that exit without user deletion — such as:
- Sessions created by scheduled runs
- One-shot
runPromptsessions - Sessions that crash with respawn disabled
…the entire session graph stays in memory indefinitely. Each session that exits without being explicitly deleted adds to permanent heap growth. On a 24-hour autonomous run this can accumulate into hundreds of MB of non-reclaimable memory.