Skip to content

fix(opencode): prevent process.exit() from killing parent terminal on Windows - #49529

Open
vad-bond wants to merge 1 commit into
anomalyco:devfrom
vad-bond:fix/win32-safe-exit
Open

vad-bond wants to merge 1 commit into
anomalyco:devfrom
vad-bond:fix/win32-safe-exit

Conversation

@vad-bond

@vad-bond vad-bond commented Sep 17, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #28673

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Since v1.14.25, exiting the TUI on Windows (via /exit, Ctrl+C, or the leader-quit bind) also kills the parent terminal. On Windows process.exit() calls ExitProcess(), which broadcasts CTRL_CLOSE_EVENT to the whole console process group. The parent shell (pwsh/cmd) is attached to that same group, so it dies together with opencode. On POSIX process.exit() only affects the calling process, which is why the bug is Windows-only.

Fix: a safeExit() helper. On Windows it sets process.exitCode and lets the process end naturally, so only opencode detaches from the console and the shell survives. On other platforms it keeps the existing process.exit() behaviour so the force-exit path that reaps MCP servers ignoring SIGTERM is unchanged.

Applied at the two exit points of the default (server + TUI) flow:

  • packages/opencode/src/index.ts – CLI entry finally block
  • packages/opencode/src/cli/cmd/tui.ts – TUI thread clean exit

Previous attempts

This is a re-submission of the same fix. Earlier PRs were auto-closed by the PR cleanup bot before CI ever ran (first-time-contributor workflows need a maintainer to approve the run):

This PR builds on #29281/#29343 with the compilation issue reported there fixed (the bare return in the module-level finally is replaced by the safeExit() helper call; on Windows the process now exits naturally via process.exitCode instead of returning from module scope).

How did you verify your code works?

  • Runtime check on Windows: with process.exitCode preset, safeExit() returns instead of exiting, the process ends naturally with the correct code, and the parent shell is left alive.
  • bun run typecheck passes for the opencode package (the enterprise/stats-server failures are pre-existing and unrelated).
  • oxlint reports no new issues in the touched files.
  • POSIX path unchanged: process.exit() is still called, preserving the force-exit behaviour for hanging subprocesses.

Screenshots / recordings

Not a UI change: the shell keeps running and the prompt returns instead of the pane closing.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

… Windows

On Windows, process.exit() calls ExitProcess(), which broadcasts CTRL_CLOSE_EVENT to the whole console process group. The parent shell (pwsh/cmd) is attached to that group, so exiting the TUI (via /exit, Ctrl+C or the leader-quit bind) kills the parent terminal too (anomalyco#28673).

Replace the two exit points (CLI entry skip, TUI thread) with a safeExit() helper that on Windows sets process.exitCode and lets the process end naturally, keeping the original process.exit() behavior on POSIX where it does not affect the console group.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

I found a potentially related PR:

#22002 - fix(win32): prevent TUI exit from closing terminal window

This PR appears to address the same issue: preventing the TUI exit from closing the parent terminal window on Windows. Since PR #22002 is older and seems to be addressing the exact same problem, you should verify whether it was:

  1. Already merged (and this is a follow-up or regression fix)
  2. Closed without merging (and this is a proper fix)
  3. Still open (in which case they should be consolidated)

Check the status and details of PR #22002 to confirm whether this is a true duplicate or a separate attempt to fix the same issue.

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.

Regression: /exit and Ctrl+C kill parent terminal process on Windows since v1.14.25

1 participant