Ctrl+C should not cancel ReadFile/ReadConsole when the signal is handled and the console is in VT input mode #7034

Open
opened 2026-01-31 00:53:22 +00:00 by claunia · 4 comments
Owner

Originally created by @alexrp on GitHub (Mar 20, 2020).

Run this C program on Linux:

#include <signal.h>
#include <unistd.h>

int main()
{
    char buf[4096];

    signal(SIGINT, SIG_IGN);

    write(STDOUT_FILENO, "reading: ", 9);
    ssize_t len = read(STDIN_FILENO, buf, sizeof(buf));
    write(STDOUT_FILENO, buf, len);

    return 0;
}

Since SIGINT is ignored, what will happen here is that ^C will be shown in the output (but not passed through to the program since we're not in raw mode), all input on the current line prior to pressing Ctrl+C will be dropped when the current line is submitted (e.g. aaa^Cbbb will return bbb), and importantly, the read system call will not be interrupted.

This differs from the behavior on Windows (see https://github.com/microsoft/terminal/issues/334#issuecomment-601788840) where ReadFile/ReadConsole will be interrupted by a Ctrl+C even when a handler is set up.

So, I think there is a case to be made here that Ctrl+C on Windows should not interrupt ReadFile/ReadConsole at all if a handler (registered with SetConsoleCtrlHandler) has suppressed the signal and the input mode has ENABLE_VIRTUAL_TERMINAL_INPUT set.

Originally created by @alexrp on GitHub (Mar 20, 2020). Run this C program on Linux: ```c #include <signal.h> #include <unistd.h> int main() { char buf[4096]; signal(SIGINT, SIG_IGN); write(STDOUT_FILENO, "reading: ", 9); ssize_t len = read(STDIN_FILENO, buf, sizeof(buf)); write(STDOUT_FILENO, buf, len); return 0; } ``` Since `SIGINT` is ignored, what will happen here is that `^C` will be shown in the output (but not passed through to the program since we're not in raw mode), all input on the current line prior to pressing Ctrl+C will be dropped when the current line is submitted (e.g. `aaa^Cbbb` will return `bbb`), and importantly, the `read` system call will not be interrupted. This differs from the behavior on Windows (see https://github.com/microsoft/terminal/issues/334#issuecomment-601788840) where `ReadFile`/`ReadConsole` will be interrupted by a Ctrl+C even when a handler is set up. So, I think there is a case to be made here that Ctrl+C on Windows should not interrupt `ReadFile`/`ReadConsole` at all **if** a handler (registered with `SetConsoleCtrlHandler`) has suppressed the signal **and** the input mode has `ENABLE_VIRTUAL_TERMINAL_INPUT` set.
claunia added the Product-ConhostIssue-TaskArea-Server labels 2026-01-31 00:53:22 +00:00
Author
Owner

@DHowett-MSFT commented on GitHub (Mar 20, 2020):

I believe this is ENABLE_PROCESSED_INPUT at work; it explicitly calls out handling ^C.

(dhowett-sl) ~\src % ./rci 0x201      # VT, PROCESSED
UNICODE. ^Z TO EXIT
--
  REP   VK  VSC CHAR          CTRL
- --- ---- ---- ---- ---- --------
^ 001 000d 001c 000d ^M   00000000
v 001 0011 001d 0000 ^@   00000008
(I press ^C, it exits)
(dhowett-sl) ~\src % ./rci 0x200      # VT Only
UNICODE. ^Z TO EXIT
--
  REP   VK  VSC CHAR          CTRL
- --- ---- ---- ---- ---- --------
^ 001 000d 001c 000d ^M   00000000
v 001 0011 001d 0000 ^@   00000008
v 001 0000 0000 0003 ^C   00000000
^ 001 0043 002e 0003 ^C   00000008
@DHowett-MSFT commented on GitHub (Mar 20, 2020): I believe this is `ENABLE_PROCESSED_INPUT` at work; it explicitly calls out handling ^C. ``` (dhowett-sl) ~\src % ./rci 0x201 # VT, PROCESSED UNICODE. ^Z TO EXIT -- REP VK VSC CHAR CTRL - --- ---- ---- ---- ---- -------- ^ 001 000d 001c 000d ^M 00000000 v 001 0011 001d 0000 ^@ 00000008 (I press ^C, it exits) ``` ``` (dhowett-sl) ~\src % ./rci 0x200 # VT Only UNICODE. ^Z TO EXIT -- REP VK VSC CHAR CTRL - --- ---- ---- ---- ---- -------- ^ 001 000d 001c 000d ^M 00000000 v 001 0011 001d 0000 ^@ 00000008 v 001 0000 0000 0003 ^C 00000000 ^ 001 0043 002e 0003 ^C 00000008 ```
Author
Owner

@alexrp commented on GitHub (Mar 20, 2020):

That sounds right. But disabling ENABLE_PROCESSED_INPUT would (as far as I can tell from the docs) also break other special keys like backspace.

@alexrp commented on GitHub (Mar 20, 2020): That sounds right. But disabling `ENABLE_PROCESSED_INPUT` would (as far as I can tell from the docs) also break other special keys like backspace.
Author
Owner

@DHowett-MSFT commented on GitHub (Mar 27, 2020):

Until we get a plan together for this (which will likely only come out with the next major release of Windows (or in Windows Terminal, because Terminal ships a newer version of conhost)), is it sufficient to just keep Reading?

You've found an ever-growing number of edge cases using PROCESSED and VT input simultaneously. I'm not sure it's something we formally validated, as applications generally choose to go all-in on Windows events xor VT-raw.

@DHowett-MSFT commented on GitHub (Mar 27, 2020): Until we get a plan together for this (which will likely only come out with the next major release of Windows (or in Windows Terminal, because Terminal ships a newer version of conhost)), is it sufficient to just keep `Read`ing? You've found an ever-growing number of edge cases using PROCESSED and VT input simultaneously. I'm not sure it's something we formally validated, as applications generally choose to go all-in on Windows events _xor_ VT-raw.
Author
Owner

@alexrp commented on GitHub (Mar 27, 2020):

Hmm, it would be sufficient if the return value was ERROR_OPERATION_ABORTED. That's basically equivalent to the situation on Unix where a read system call can be interrupted by a signal, which results in errno being set to EINTR, indicating that you should just retry the call.

Unfortunately, #334 is making that a bit hard to do. 😄 But still, maybe under specific circumstances I can get away with using ReadConsole to at least work around the issue in the most common cases.

@alexrp commented on GitHub (Mar 27, 2020): Hmm, it would be sufficient if the return value was `ERROR_OPERATION_ABORTED`. That's basically equivalent to the situation on Unix where a `read` system call can be interrupted by a signal, which results in `errno` being set to `EINTR`, indicating that you should just retry the call. Unfortunately, #334 is making that a bit hard to do. 😄 But still, maybe under specific circumstances I can get away with using `ReadConsole` to at least work around the issue in the most common cases.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#7034