Skip to content

Commit

Permalink
Rollup merge of rust-lang#89433 - arlosi:stdin-fix, r=joshtriplett
Browse files Browse the repository at this point in the history
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
  • Loading branch information
matthiaskrgr committed Oct 14, 2021
2 parents f590a97 + 273e522 commit 7aca070
Showing 1 changed file with 19 additions and 9 deletions.
28 changes: 19 additions & 9 deletions library/std/src/sys/windows/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 7aca070

Please sign in to comment.