Skip to content

fix(pty): free Rust session on kill() to stop FD leak (#974)#980

Merged
xiaolai merged 1 commit into
mainfrom
fix/pty-close-leak-974
May 30, 2026
Merged

fix(pty): free Rust session on kill() to stop FD leak (#974)#980
xiaolai merged 1 commit into
mainfrom
fix/pty-close-leak-974

Conversation

@xiaolai
Copy link
Copy Markdown
Owner

@xiaolai xiaolai commented May 30, 2026

Summary

Fixes #974VMarkPty.kill() leaked a Rust session map entry (FDs, channels, child handle) on every terminal close.

kill() removes the pty:exit listener via _cleanup() before pty_kill, so when the process dies the exit handler that calls pty_close never runs. Over a long session, repeatedly opening/closing terminals exhausts FDs.

Fix

  • kill() now calls pty_close after pty_kill, in a .finally() so a failed kill still frees the session.
  • The setup-time guard path (kill during in-flight spawn) tears down listeners eagerly too, so it now calls pty_close after pty_kill as well.
  • Synced the module header (pty_close runs from the exit handler or directly from kill()/guard when listeners were torn down first).

Test

New src/lib/pty.test.ts (real implementation — vi.unmock("@/lib/pty") since the global setup mocks the module):

  • kill() invokes pty_close after pty_kill for the same pid (exactly once on the normal path).
  • The setup-guard race path also frees the session via pty_close.

RED before the fix (both fail), GREEN after.

Scope

Per the issue's scope guard: only src/lib/pty.ts + the new sibling test. No changes to src-tauri/src/pty.rs (the Rust side is correct), the EventEmitter, or anything else.

Verification

  • pnpm test src/lib/pty.test.ts passes
  • pnpm check:all green (lint + coverage + build + size)

kill() removes the pty:exit listener via _cleanup() before pty_kill, so the
exit handler that calls pty_close never runs — every terminal close leaked a
Rust session map entry (FDs, channels, child handle). Call pty_close explicitly
after pty_kill (in finally, so a failed kill still frees the session), and add
the same close to the setup-time guard path that also tears down listeners
eagerly. Add a regression test asserting pty_close is invoked after kill().

Closes #974
@xiaolai xiaolai merged commit 30d834a into main May 30, 2026
8 checks passed
@xiaolai xiaolai deleted the fix/pty-close-leak-974 branch May 30, 2026 17:06
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.

[audit] terminal: VMarkPty.kill() leaks Rust session map entry (pty_close never called)

1 participant