Skip to content

Don't reattach restored terminal editors to another window's terminal - #341692

Merged
Anthony Kim (anthonykim1) merged 6 commits into
mainfrom
anthonykim1/verify-restored-terminal-pid
Oct 15, 2026
Merged

Anthony Kim (anthonykim1) merged 6 commits into
mainfrom
anthonykim1/verify-restored-terminal-pid

Conversation

@anthonykim1

@anthonykim1 Anthony Kim (anthonykim1) commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Resolves: #341502

  • Pass the pid saved with a restored terminal editor through attachToRevivedProcess.
  • When there is no revived process, reattach by the editor's original persistent process ID only if that process still has the saved pid. IDs restart from 1 whenever the pty host restarts, so the ID can belong to another window's running terminal; a mismatch now creates a new terminal, the same as a missing ID.
  • Keep attaching revived processes by their new ID without a pid check, since reviving starts a new process.
  • Keep the current behavior when the saved pid is unknown (0), and for terminals moved between windows or picked with Attach to Session, which still attach by ID only.
  • Clear the shell pid when a relaunch installs its new process. A terminal editor saved before the new shell is ready now stores pid 0 instead of pairing the new ID with the previous shell's pid, which the check above would refuse.
  • Add an optional pid to IPtyService.attachToProcess, checked on the pty host, and forward it through PtyHostService.
  • Register PtyService's RPC trace listeners so the service can be constructed in leak-checked tests.
  • Export LocalTerminalBackend so its reattach routing can be tested.
  • Remote terminal editors restore through attachToProcess directly and are not changed here; the attachToRevivedProcess docs now say only the local backend checks the pid.

How to test

  1. Launch VS Code with only folder B open, run Terminal: Create New Terminal in Editor Area three times, close B's window, then quit VS Code.
  2. Launch VS Code with folder A, create three terminals, and run sleep 600 in the third.
  3. Use File > New Window and open folder B.

Expected: B starts new terminals, A's terminals stay in A, and sleep keeps running. The Pty Host log shows Persistent process reconnection "N" failed Pty N has pid X, expected Y. Before this change, B showed A's running terminals as editor tabs, and typing in or closing them affected A.

Also check that reloading keeps the same shells, that Terminal: Relaunch Active Terminal in an editor terminal followed by a reload reattaches to the relaunched shell, and that quitting and reopening restores the terminal history.

Validation:

  • ./scripts/test.sh --run src/vs/platform/terminal/test/node/ptyService.test.ts --run src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts --run src/vs/workbench/contrib/terminal/test/electron-browser/localTerminalBackend.test.ts: 17 passing. The new tests fail without the changes: without clearing the pid, a relaunched terminal reports { id: 2, pid: 1001 } before it's ready, and with the previous backend routing a mismatched pid attaches to the other process.
  • ./scripts/test.sh --runGlob "**/terminal/**/*.test.js": 763 passing, 14 pending. --runGlob "**/terminalContrib/**/*.test.js": 2749 passing, 176 pending. --runGlob "**/contrib/tasks/**/*.test.js": 90 passing, 5 pending.
  • npm run typecheck-client: passed.
  • npm run eslint -- <changed files>: passed.
  • In Code OSS built from this branch with real shells:
    • The steps above refused all three saved IDs (Pty 2 has pid 5226, expected 99559), started new terminals in B, and left A's terminals and sleep running.
    • Reloading kept the same editor and panel shells, relaunching an editor terminal and then reloading reattached the relaunched shell, and quitting and reopening revived the terminals with their history.
    • With the pty host paused in the relaunched process's start (--inspect-ptyhost), the periodic save stored the editor as {"id":4,"pid":0}. After killing the renderer and choosing Reopen, the editor reattached the relaunched shell. On the previous commit, the same steps stored the previous shell's pid, refused the relaunched shell, and started a second one.

Inspirations from:

Persistent process IDs restart from 1 when the pty host restarts, but terminal
editors keep the IDs they were saved with. When a restored editor had no
revived process, it reattached by its saved ID, which can now belong to a
running terminal in another window.

Pass the pid saved with the editor and only reattach by the original ID when
that process still has the same pid; otherwise a new terminal is created.

Also register PtyService's RPC trace listeners so the service can be created
in leak-checked tests.

Fixes #341502
Copilot AI balanced review requested due to automatic review settings October 15, 2026 06:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No actionable defects remain in the scoped attachment safeguard; reported validation was not rerun.

0 open findings

What changed in this PR

Prevents restored local terminal editors from attaching to another window’s terminal when persistent process IDs are reused, addressing #341502.

Changes:

  • Validates the saved PID before attaching to an original, non-revived process.
  • Preserves revived-process and ID-only attachment behavior.
  • Adds regression tests and registers trace listeners for disposal.
File Description
src/​vs/​workbench/​contrib/​terminal/​test/​browser/​terminalProcessManager.test.ts Tests saved PID forwarding.
src/​vs/​workbench/​contrib/​terminal/​electron-browser/​localTerminalBackend.ts Checks PID on fallback attachment.
src/​vs/​workbench/​contrib/​terminal/​browser/​terminalProcessManager.ts Passes the saved PID during restoration.
src/​vs/​platform/​terminal/​test/​node/​ptyService.test.ts Tests matching, mismatched, and omitted PIDs.
src/​vs/​platform/​terminal/​node/​ptyService.ts Rejects PID mismatches and tracks listener disposal.
src/​vs/​platform/​terminal/​node/​ptyHostService.ts Forwards the optional PID.
src/​vs/​platform/​terminal/​common/​terminal.ts Updates attachment contracts and documentation.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Relaunching installs the new persistent process before its shell reports
a pid, so a terminal editor saved in between paired the new ID with the
previous shell's pid, and restoring it then refused the intended process.
Clear the pid when the new process is installed, so it's saved as unknown
until the shell is ready.

Also cover the local backend's reattach routing with tests and note that
only the local backend checks the pid.
@anthonykim1
Anthony Kim (anthonykim1) marked this pull request as ready for review October 15, 2026 16:43
@anthonykim1

Copy link
Copy Markdown
Contributor Author

Megan Rogge (@meganrogge) This is an interesting one

Comment on lines +243 to +244
// The original ID may belong to another window's process after a pty host restart
return await this.attachToProcess(id, pid > 0 ? pid : undefined);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why would this happen?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For example, workspace B can have a saved terminal  { id: 21, pid: 72265 } . After a restart, workspace A can create a different terminal that is assigned ID 21. If B is then reopened and there is no revival mapping, the old code falls back to ID 21 and attaches to A’s terminal. Comparing the saved PID would prevent that.

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Base: d771f022 Current: df885a14

No screenshot changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Restored terminal editor attaches to a running terminal of another open window (persistent process IDs reused after pty host restart)

4 participants