From d52625dcae748bae93f7336ee6e236f7c2a53894 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Sun, 12 Jan 2020 23:53:53 -0700 Subject: [PATCH] bpo-28166: WindowsConsoleIO misbehavior when Ctrl+C is ignored Continue to read if SIGINT is ignored or the handler doesn't raise an exception. Co-Authored-By: Valeriya Sinevich --- .../next/Windows/2020-01-12-23-52-49.bpo-28166.dZ-Mz9.rst | 2 ++ Modules/_io/winconsoleio.c | 5 +++-- Parser/myreadline.c | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2020-01-12-23-52-49.bpo-28166.dZ-Mz9.rst diff --git a/Misc/NEWS.d/next/Windows/2020-01-12-23-52-49.bpo-28166.dZ-Mz9.rst b/Misc/NEWS.d/next/Windows/2020-01-12-23-52-49.bpo-28166.dZ-Mz9.rst new file mode 100644 index 000000000000000..85bafc57fa3780e --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-01-12-23-52-49.bpo-28166.dZ-Mz9.rst @@ -0,0 +1,2 @@ +``WindowsConsoleIO``: Continue to read when interrupted by Ctrl+C if +``SIGINT`` is ignored or the handler doesn't raise an exception. diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 94760acd47bf251..0e2239bf7ba03a3 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -575,14 +575,15 @@ read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) { break; err = 0; HANDLE hInterruptEvent = _PyOS_SigintEvent(); - if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE) - == WAIT_OBJECT_0) { + DWORD state = WaitForSingleObjectEx(hInterruptEvent, 100, FALSE); + if (state == WAIT_OBJECT_0 || state == WAIT_TIMEOUT) { ResetEvent(hInterruptEvent); Py_BLOCK_THREADS sig = PyErr_CheckSignals(); Py_UNBLOCK_THREADS if (sig < 0) break; + continue; } } *readlen += n; diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 43e5583b8bcc431..a20a131b753c92e 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -131,14 +131,15 @@ _PyOS_WindowsConsoleReadline(HANDLE hStdIn) goto exit; err = 0; HANDLE hInterruptEvent = _PyOS_SigintEvent(); - if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE) - == WAIT_OBJECT_0) { + DWORD state = WaitForSingleObjectEx(hInterruptEvent, 100, FALSE); + if (state == WAIT_OBJECT_0 || state == WAIT_TIMEOUT) { ResetEvent(hInterruptEvent); PyEval_RestoreThread(_PyOS_ReadlineTState); s = PyErr_CheckSignals(); PyEval_SaveThread(); if (s < 0) goto exit; + continue; } break; }