gh-72353: Continue reading from the console after ignored Ctrl+C (GH-155434)

If the console cancels a read because of Ctrl+C, but the SIGINT handler
does not raise an exception, restart the read instead of ending it as if
at end of file.

Co-authored-by: Valeriya Sinevich <valeriya.sinevich@phystech.edu>
Co-authored-by: Zackery Spytz <zspytz@gmail.com>
diff --git a/Misc/NEWS.d/next/Windows/2026-08-09-14-20-00.gh-issue-72353.Vw7Kq2.rst b/Misc/NEWS.d/next/Windows/2026-08-09-14-20-00.gh-issue-72353.Vw7Kq2.rst
new file mode 100644
index 0000000..95c7718
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2026-08-09-14-20-00.gh-issue-72353.Vw7Kq2.rst
@@ -0,0 +1,3 @@
+Reading from the console on Windows now continues if the read was cancelled
+by Ctrl+C, but the :const:`~signal.SIGINT` handler did not raise an
+exception.  Previously the read ended as if at end of file.
diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c
index 4cd7109..e96c5bd 100644
--- a/Modules/_io/winconsoleio.c
+++ b/Modules/_io/winconsoleio.c
@@ -644,8 +644,8 @@ 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) {
                 ResetEvent(hInterruptEvent);
                 Py_BLOCK_THREADS
                 sig = PyErr_CheckSignals();
@@ -653,6 +653,13 @@ read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) {
                 if (sig < 0)
                     break;
             }
+            else if (state != WAIT_TIMEOUT) {
+                err = GetLastError();
+                break;
+            }
+            /* The console cancelled the read and flushed its input buffer,
+               but no exception was raised.  Start the read over. */
+            continue;
         }
         *readlen += n;
 
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 457b959..339f55a 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -162,8 +162,8 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, 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) {
                 ResetEvent(hInterruptEvent);
                 PyEval_RestoreThread(tstate);
                 s = PyErr_CheckSignals();
@@ -172,7 +172,13 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn)
                     goto exit;
                 }
             }
-            break;
+            else if (state != WAIT_TIMEOUT) {
+                err = GetLastError();
+                goto exit;
+            }
+            /* The console cancelled the read and flushed its input buffer,
+               but no exception was raised.  Start the read over. */
+            continue;
         }
 
         total_read += n_read;