-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Execution continues after stdin read_line when ctrl-c is pressed on Windows #89177
Comments
Is this specific to reading stdin? Lots of things about this seem strange (launching a separate thread?!) but I would be really surprised to hear this only happens for stdin and nothing else. If so adding the check in read_line won't be sufficient. |
I think the issue is specific to stdin. I don't think you could (for example) embed a ctrl+c in a file and have it terminate the reading process. Windows does seem to launch a thread to handle ctrl-c. From https://docs.microsoft.com/en-us/windows/console/ctrl-c-and-ctrl-break-signals
My issue description might not have been quite clear. rust/library/std/src/sys/windows/stdio.rs Line 281 in cfff31b
|
Hmm, what happens if the user presses Ctrl+C while the program is reading a file? Won't the program execution continue for a few milliseconds with only a partial read? |
Yes, but there's not really noticeable to the user. The file reading wouldn't be waiting for user input in order to begin. The few milliseconds delay in that case would be the same as any other latency (keyboard, os, etc.). The problem with reading from The behavior becomes even more clear if you install a ctrl-c handler (such as with the ctrlc::set_handler(|| println!("Caught ctrl-c")).unwrap();
let bytes = std::io::stdin().lock().read_line(&mut line)?; On other platforms, the program will just print "Caught ctrl-c" for each press, and continue blocking. While on Windows execution will also continue past the |
Fix ctrl-c causing reads of stdin to return empty on Windows. Pressing ctrl+c (or ctrl+break) on Windows caused a blocking read of stdin to unblock and return empty, unlike other platforms which continue to block. On ctrl-c, `ReadConsoleW` will return success, but also set `LastError` to `ERROR_OPERATION_ABORTED`. This change detects this case, and re-tries the call to `ReadConsoleW`. Fixes rust-lang#89177. See issue for further details. Tested on Windows 7 and Windows 10 with both MSVC and GNU toolchains
Fix ctrl-c causing reads of stdin to return empty on Windows. Pressing ctrl+c (or ctrl+break) on Windows caused a blocking read of stdin to unblock and return empty, unlike other platforms which continue to block. On ctrl-c, `ReadConsoleW` will return success, but also set `LastError` to `ERROR_OPERATION_ABORTED`. This change detects this case, and re-tries the call to `ReadConsoleW`. Fixes rust-lang#89177. See issue for further details. Tested on Windows 7 and Windows 10 with both MSVC and GNU toolchains
When blocking on
read_line
fromstdin
, if I press Ctrl-C, program execution continues past the blockingread_line
call for a short period before the program is terminated on Windows.I tried this code:
I expected to see this happen: Program should exit after pressing Ctrl-C without printing the second message.
Instead, this happened: Program prints
This should not print if Ctrl-C was pressed. Read 0 bytes
after pressing Ctrl-C.This only occurs on Windows. *nix platforms exit without printing the second message.
Since program execution continues after ctrl-c, unexpected results occur. For example, running
cargo login
, then pressingctrl-c
instead of entering a token,cargo
will overwrite the saved token with""
on Windows.*nix platforms continue blocking in
read_line
when ctrl-c is pressed. Including if a handler for ctrl-c is set up.Why it's happening
read_line
calls the WindowsReadConsoleW
API. That API returns success with an empty buffer for Ctrl-C (and Ctrl-Break).read_line
then also returnsOk
. In parallel, Windows uses a separate thread that raises an exception for the ctrl-c event that terminates the process. This leads to a short window of time where program execution continues after ctrl-c is pressed.Potential solutions
Even though
ReadConsoleW
returns success, it also sets LastError toERROR_OPERATION_ABORTED
for this case, so we can detect this case.The Rust standard library calls
ReadConsoleW
hererust/library/std/src/sys/windows/stdio.rs
Line 295 in cfff31b
Re-try the call immediately
We could re-try the call to
ReadConsoleW
immediately for this specific case by adding a check after theReadConsoleW
call.Return an error
Alternately, after the call to
ReadConsoleW
, we could add a check to detect this error and propagate it:Returning an error still differs from *nix, in that it raises an error instead of continuing to block.
Return an error then retry
We could return the error as described above, and change the mapping of
ERROR_OPERATION_ABORTED
fromErrorKind::TimedOut
toErrorKind::Interrupted
.rust/library/std/src/sys/windows/mod.rs
Line 79 in cfff31b
ErrorKind::Interrupted
would then re-tried theBufRead
infrastructure.Do nothing
Maybe this is expected behavior and we want a difference between Windows and *nix here.
Meta
Occurs in both stable and nightly.
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: