diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-10-14 16:06:44 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-14 16:06:44 +0200 |
| commit | d1777917915f59df0407ddeb16aa9e987481784c (patch) | |
| tree | 024d7358ba4bd36b0c19c184f3f971d257f7c5f9 | |
| parent | f9c9774aea914bc2be7ad1bb466a8104592a7933 (diff) | |
| parent | 273e522af6c7b28704688b2a7b8b423c7472fb3c (diff) | |
| download | rust-d1777917915f59df0407ddeb16aa9e987481784c.tar.gz rust-d1777917915f59df0407ddeb16aa9e987481784c.zip | |
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
| -rw-r--r-- | library/std/src/sys/windows/stdio.rs | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index 2719a530dfd..a4fe5f67f69 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -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; |
