-
Notifications
You must be signed in to change notification settings - Fork 0
fix(codeflow): [CI/rebase] Terminal Sessions Memory Leak #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ const IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 min — sessions idle this long ar | |
| const EXPIRED_OUTPUT_GRACE_MS = 60 * 1000; // 60 s — after exit, retain snapshot for this long before deletion | ||
| const PURGE_INTERVAL_MS = 30 * 1000; // 30 s — background sweep cadence | ||
| const SIGKILL_TIMEOUT_MS = 5 * 1000; // 5 s — SIGKILL escalation if SIGTERM is ignored | ||
| const MAX_SESSIONS = 50; // hard cap on concurrent sessions to bound resource use | ||
|
|
||
| const sessions = new Map<string, InternalTerminalSession>(); | ||
| let sessionCounter = 0; | ||
|
|
@@ -245,6 +246,14 @@ export const createTerminalSession = async (options?: { | |
| cwd?: string; | ||
| title?: string; | ||
| }): Promise<TerminalSessionSnapshot> => { | ||
| // Reap idle/expired sessions first so the cap reflects live sessions only. | ||
| purgeIdleSessions(); | ||
| if (sessions.size >= MAX_SESSIONS) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After 50 shells terminate naturally, their entries remain in Useful? React with 👍 / 👎.
Comment on lines
+250
to
+251
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Concurrent requests bypass the cap createTerminalSession checks sessions.size without reserving a slot, then yields while awaiting resolveInitialCwd before registering the new session. Concurrent calls can therefore all pass below 50 and subsequently spawn and retain more than the intended maximum number of child processes. Agent Prompt
Comment on lines
+249
to
+251
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Idle sessions block new terminals createTerminalSession invokes purgeIdleSessions but immediately counts every remaining map entry, while that purge only signals idle running sessions and deliberately leaves them mapped. At 50 idle sessions, creation still throws until child closure and the subsequent output-grace expiry, even though all sessions have already been selected for reaping. Agent Prompt
|
||
| throw new Error( | ||
| `Terminal session limit reached (${MAX_SESSIONS}). Close an existing session before opening a new one.` | ||
|
Comment on lines
+249
to
+253
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When many requests create sessions simultaneously while the map has room, every call performs this size check and then suspends at Useful? React with 👍 / 👎. |
||
| ); | ||
| } | ||
|
|
||
| const cwd = await resolveInitialCwd(options?.cwd); | ||
| const shell = getShellPath(); | ||
| const child = spawn(shell, [], { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Session limits never reach users
🐞 Bug≡ CorrectnessAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools