Skip to content

fix: solve #2960 — PTY spawn failure leaves zombie sessions blocking new terminals#2963

Merged
Kitenite merged 2 commits into
mainfrom
triage/issue-2960-23671455762
Mar 28, 2026
Merged

fix: solve #2960 — PTY spawn failure leaves zombie sessions blocking new terminals#2963
Kitenite merged 2 commits into
mainfrom
triage/issue-2960-23671455762

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Mar 27, 2026

Summary

  • Root cause: When pty.spawn() fails (e.g. posix_spawnp failed) in pty-subprocess.ts, the subprocess sends an error frame but does not exit. This leaves session.isAlive returning true for a session with no PTY, so TerminalHost stores and attaches to a broken session — blocking new terminal creation.
  • Fix 1 (pty-subprocess.ts): Exit the subprocess with code 1 after spawn failure, so the daemon correctly detects the session as dead via session.isAlive === false.
  • Fix 2 (terminal-host.ts): After the ready timeout, also check session.pid === null to catch edge cases where the subprocess is alive but the PTY never spawned (belt-and-suspenders defense).
  • Tests: Added terminal-host.test.ts with 4 tests covering spawn failure scenarios, verifying the bug behavior and the fix.

Test plan

  • Reproduction test confirms bug: session.isAlive is true when subprocess is alive but PTY failed to spawn
  • Fix test confirms: subprocess exit after spawn failure makes session.isAlive return false
  • Fix test confirms: session.pid === null check catches broken sessions even if subprocess is alive
  • Healthy session test confirms: normal flow still works (isAlive=true, pid set)
  • All 30 terminal-host tests pass
  • Lint clean

Closes #2960


Summary by cubic

Fixes zombie terminal sessions when pty.spawn() fails. The subprocess now exits on spawn error and TerminalHost rejects sessions with no PID, unblocking new terminals. Closes #2960.

  • Bug Fixes

    • Exit subprocess with code 1 after spawn failure in pty-subprocess.ts, so session.isAlive becomes false.
    • After the ready timeout in terminal-host.ts, also check session.pid === null and reject the session.
    • Add tests for spawn failure, PID-null timeout, and healthy sessions.
  • Refactors

    • Minor deslop: schema reuse in chat router, simpler error text in workspace-client, and a tighter auth token check in PskHostAuthProvider.

Written for commit f639c7e. Summary will update on new commits.

…sessions (#2960)

When pty.spawn() fails (e.g. posix_spawnp failed), the subprocess sent
an error frame but stayed alive. This left session.isAlive returning
true for a broken session with no PTY, causing TerminalHost to store
and attach to it — blocking new terminal creation.

Two fixes:
- pty-subprocess.ts: exit with code 1 after spawn failure so the daemon
  correctly detects the session as dead
- terminal-host.ts: also check session.pid after ready timeout to catch
  edge cases where subprocess is alive but PTY never spawned
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/main/terminal-host/terminal-host.test.ts">

<violation number="1" location="apps/desktop/src/main/terminal-host/terminal-host.test.ts:141">
P1: Using real-looking fake PIDs with `session.dispose()` can send SIGKILL to unrelated OS processes during test runs.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

const terminalHostWouldReject = !session.isAlive;
expect(terminalHostWouldReject).toBe(false); // BUG: should be true!

await session.dispose();
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Using real-looking fake PIDs with session.dispose() can send SIGKILL to unrelated OS processes during test runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/terminal-host/terminal-host.test.ts, line 141:

<comment>Using real-looking fake PIDs with `session.dispose()` can send SIGKILL to unrelated OS processes during test runs.</comment>

<file context>
@@ -0,0 +1,263 @@
+		const terminalHostWouldReject = !session.isAlive;
+		expect(terminalHostWouldReject).toBe(false); // BUG: should be true!
+
+		await session.dispose();
+	});
+
</file context>
Fix with Cubic

@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented Mar 28, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

@Kitenite Kitenite merged commit 8af71b6 into main Mar 28, 2026
14 checks passed
@Kitenite Kitenite deleted the triage/issue-2960-23671455762 branch March 28, 2026 19:22
siarhei-belavus pushed a commit to siarhei-belavus/localset that referenced this pull request Mar 30, 2026
…s blocking new terminals (superset-sh#2963)

* fix(desktop): exit subprocess on PTY spawn failure to prevent zombie sessions (superset-sh#2960)

When pty.spawn() fails (e.g. posix_spawnp failed), the subprocess sent
an error frame but stayed alive. This left session.isAlive returning
true for a broken session with no PTY, causing TerminalHost to store
and attach to it — blocking new terminal creation.

Two fixes:
- pty-subprocess.ts: exit with code 1 after spawn failure so the daemon
  correctly detects the session as dead
- terminal-host.ts: also check session.pid after ready timeout to catch
  edge cases where subprocess is alive but PTY never spawned

* Deslop

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kiet Ho <hoakiet98@gmail.com>
(cherry picked from commit 8af71b6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] new terminal/pane creation intermittently fails in long-lived sessions while existing terminal state is preserved

1 participant