Skip to content

Commit 3a54fbc

Browse files
branchseerclaude
andcommitted
Fix incorrect comment: ConPTY sets CTRL_C ignore flag, not Rust runtime
Investigation confirmed Rust std, ctrlc crate, and portable-pty have zero calls to SetConsoleCtrlHandler(NULL, TRUE). The inheritable ignore flag is set by the Windows ConPTY subsystem for spawned processes. The SetConsoleCtrlHandler(None, 0) workaround is still needed — without it the test times out on Windows — but the comment was wrong about the source. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4e48134 commit 3a54fbc

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

crates/pty_terminal/tests/terminal.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,12 @@ fn send_ctrl_c_interrupts_process() {
305305
// On macOS/Windows, use ctrlc which works fine (no .init_array/musl issue).
306306
#[cfg(not(target_os = "linux"))]
307307
{
308-
// On Windows, clear the "ignore CTRL_C" flag set by Rust runtime
309-
// so that CTRL_C_EVENT reaches the ctrlc handler.
308+
// On Windows, an ancestor process may have been created with
309+
// CREATE_NEW_PROCESS_GROUP, which implicitly sets the per-process
310+
// CTRL_C ignore flag (CONSOLE_IGNORE_CTRL_C in PEB ConsoleFlags).
311+
// This flag is inherited by all descendants and silently drops
312+
// CTRL_C_EVENT before it reaches registered handlers. Clear it.
313+
// Ref: https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
310314
#[cfg(windows)]
311315
{
312316
// SAFETY: Declaring correct signature for SetConsoleCtrlHandler from kernel32.

crates/vite_task_bin/src/vtt/exit_on_ctrlc.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,23 @@
33
/// Sets up a Ctrl+C handler, emits a "ready" milestone, then waits.
44
/// When Ctrl+C is received, prints "ctrl-c received" and exits.
55
pub fn run() -> Result<(), Box<dyn std::error::Error>> {
6-
// On Windows, Rust's runtime sets `SetConsoleCtrlHandler(NULL, TRUE)` which
7-
// ignores CTRL_C_EVENT. This flag is inherited by child processes and takes
8-
// precedence over registered handlers. Clear it before registering ours.
6+
// On Windows, an ancestor process (e.g. cargo, the test harness) may have
7+
// been created with CREATE_NEW_PROCESS_GROUP, which implicitly calls
8+
// SetConsoleCtrlHandler(NULL, TRUE) and sets CONSOLE_IGNORE_CTRL_C in the
9+
// PEB's ConsoleFlags. This flag is inherited by all descendants and takes
10+
// precedence over registered handlers — CTRL_C_EVENT is silently dropped.
11+
// Clear it so our handler can fire.
12+
// Ref: https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
913
#[cfg(windows)]
1014
{
11-
// SAFETY: Passing (None, FALSE) removes the "ignore CTRL_C" flag.
15+
// SAFETY: Passing (None, FALSE) clears the per-process CTRL_C ignore flag.
1216
unsafe extern "system" {
1317
fn SetConsoleCtrlHandler(
1418
handler: Option<unsafe extern "system" fn(u32) -> i32>,
1519
add: i32,
1620
) -> i32;
1721
}
18-
// SAFETY: Clearing the Rust runtime's ignore flag.
22+
// SAFETY: Clearing the inherited ignore flag.
1923
unsafe {
2024
SetConsoleCtrlHandler(None, 0);
2125
}

0 commit comments

Comments
 (0)