Rollup merge of #89433 - arlosi:stdin-fix, r=joshtriplett

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 #89177. See issue for further details.

Tested on Windows 7 and Windows 10 with both MSVC and GNU toolchains
This commit is contained in:
Matthias Krüger 2021-10-14 16:06:44 +02:00 committed by GitHub
commit d177791791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -291,15 +291,25 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
};
let mut amount = 0;
cvt(unsafe {
c::ReadConsoleW(
handle,
buf.as_mut_ptr() as c::LPVOID,
buf.len() as u32,
&mut amount,
&mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
)
})?;
loop {
cvt(unsafe {
c::SetLastError(0);
c::ReadConsoleW(
handle,
buf.as_mut_ptr() as c::LPVOID,
buf.len() as u32,
&mut amount,
&mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
)
})?;
// ReadConsoleW returns success with ERROR_OPERATION_ABORTED for Ctrl-C or Ctrl-Break.
// Explicitly check for that case here and try again.
if amount == 0 && unsafe { c::GetLastError() } == c::ERROR_OPERATION_ABORTED {
continue;
}
break;
}
if amount > 0 && buf[amount as usize - 1] == CTRL_Z {
amount -= 1;