fix(task): restore terminal mode after task exits on Windows (#34685)
On Windows, `deno task` spawns child processes (for example a dev server
like `vite`) that switch the terminal into raw mode to listen for key
presses (`press h + enter to show help`). When the task is terminated
with Ctrl+C, the child can be torn down without restoring the terminal,
leaving the user's terminal in a broken state — input echo and line
editing are disabled, so typed characters don't appear and the terminal
looks frozen.
This matches the symptoms reported in #26379 (and corroborated in the
comments: characters typed after Ctrl+C don't echo, backspace shows
`^H`, happens across PowerShell and Git Bash).
## Fix
Save the console mode before running the task and restore it once the
task and all of its child processes have finished. This guarantees that
whatever a child did to the console mode (e.g. disabling
`ENABLE_ECHO_INPUT` / `ENABLE_LINE_INPUT`), the terminal is returned to
its original state when `deno task` finishes.
- Adds `TerminalModeGuard` in `cli/util/console.rs`. It captures the
stdin/stdout console mode on `acquire()` and restores it on drop.
- It is a no-op when stdin/stdout are redirected (not a console —
`GetConsoleMode` fails so there is nothing to restore) and on
non-Windows platforms, where the child belongs to the same process group
and the shell restores the controlling terminal's line discipline.
- Wired into `run_future_forwarding_signals` in `cli/task_runner.rs`,
which wraps the entire task lifetime. The guard is declared first so it
is dropped last — after the children have been torn down by the existing
kill-signal drop guards — avoiding a race where a still-running child
re-enters raw mode after restoration.
## Testing
This is inherently a Windows-console interaction that can't be
meaningfully exercised in CI (tests run without an attached console, so
the captured mode is `None` and the guard is a no-op). Added a smoke
test verifying `acquire()`/drop don't panic. Manual verification on
Windows: run `deno task dev` in a Vite project, press Ctrl+C, and
confirm the terminal echoes input normally afterward.
Closes #26379
Closes denoland/divybot#405
---------
Co-authored-by: divybot <divybot@users.noreply.github.com>
Co-authored-by: Divy Srivastava <me@littledivy.com>