fix(win32): prevent TUI exit from closing terminal window#22002
fix(win32): prevent TUI exit from closing terminal window#22002bamboodew wants to merge 2 commits intoanomalyco:devfrom
Conversation
On Windows, exiting the TUI (Ctrl+D) causes the terminal window to close instead of returning to the shell prompt. This happens because the worker's graceful shutdown kills MCP server subprocesses, which detaches the main process from its console (GetConsoleWindow → 0x0). Two fixes: 1. **thread.ts**: On Windows, fire-and-forget the worker shutdown signal instead of awaiting it. Neither `worker.terminate()` nor awaiting the graceful shutdown is safe — both destroy the console window. Let `process.exit(0)` tear down all subprocesses instead. 2. **win32.ts**: Fix a race condition where a pending `setImmediate(enforce)` callback could re-clear `ENABLE_PROCESSED_INPUT` after `unguard()` had already restored the console mode. Move `done` flag before `enforce()` and check it on entry.
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Based on my search, I found two potentially related PRs (excluding the current PR #22002):
These PRs appear to address related but distinct platform-specific issues with terminal state management during exit. PR #22002 is specifically targeting Windows console behavior, while these others handle POSIX/general terminal concerns. |
The unconditional process.exit(0) at the end of the TUI handler causes
the Linux CI test to fail. On non-Windows platforms, the index.ts
finally{} safety-net handles process exit. Only Windows needs the
explicit exit because the worker is not terminated there.
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Issue for this PR
Closes #22003
Type of change
What does this PR do?
On Windows, Ctrl+D exit closes the terminal window instead of returning to the shell.
I traced this with kernel32 FFI (
SetConsoleCtrlHandler+GetConsoleWindowpolling). The worker's graceful shutdown kills MCPserver subprocesses, and those exits detach the main process from its console —
GetConsoleWindow()goes from a valid handle to0x0. NoCTRL_CLOSE_EVENTfires; the console is silently lost.Both
worker.terminate()andawait client.call("shutdown")trigger this.terminate()crashes the console immediately; awaitingshutdown destroys it ~4s later during MCP cleanup.
Fix in
thread.ts: On Windows, fire-and-forget the shutdown signal and skipworker.terminate(). The existingprocess.exit(0)tears everything down cleanly.Fix in
win32.ts:setImmediate(enforce)queued by thesetRawModewrapper duringrenderer.destroy()could fire afterunguard()and re-clearENABLE_PROCESSED_INPUT. Moveddoneflag beforeenforce()and check it on entry.How did you verify your code works?
tui threadtests passprocess.exitbehaviorScreenshots / recordings
N/A — terminal behavior fix, not UI change.
Checklist