Skip to content

Commit c7d6281

Browse files
serhiy-storchakaValeriyaSinevichZackerySpytz
committed
gh-72353: Continue reading from the console after ignored Ctrl+C
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>
1 parent 998b890 commit c7d6281

3 files changed

Lines changed: 21 additions & 5 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Reading from the console on Windows now continues if the read was cancelled
2+
by Ctrl+C, but the :const:`~signal.SIGINT` handler did not raise an
3+
exception. Previously the read ended as if at end of file.

Modules/_io/winconsoleio.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,22 @@ read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) {
644644
break;
645645
err = 0;
646646
HANDLE hInterruptEvent = _PyOS_SigintEvent();
647-
if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE)
648-
== WAIT_OBJECT_0) {
647+
DWORD state = WaitForSingleObjectEx(hInterruptEvent, 100, FALSE);
648+
if (state == WAIT_OBJECT_0) {
649649
ResetEvent(hInterruptEvent);
650650
Py_BLOCK_THREADS
651651
sig = PyErr_CheckSignals();
652652
Py_UNBLOCK_THREADS
653653
if (sig < 0)
654654
break;
655655
}
656+
else if (state != WAIT_TIMEOUT) {
657+
err = GetLastError();
658+
break;
659+
}
660+
/* The console cancelled the read and flushed its input buffer,
661+
but no exception was raised. Start the read over. */
662+
continue;
656663
}
657664
*readlen += n;
658665

Parser/myreadline.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn)
162162
goto exit;
163163
err = 0;
164164
HANDLE hInterruptEvent = _PyOS_SigintEvent();
165-
if (WaitForSingleObjectEx(hInterruptEvent, 100, FALSE)
166-
== WAIT_OBJECT_0) {
165+
DWORD state = WaitForSingleObjectEx(hInterruptEvent, 100, FALSE);
166+
if (state == WAIT_OBJECT_0) {
167167
ResetEvent(hInterruptEvent);
168168
PyEval_RestoreThread(tstate);
169169
s = PyErr_CheckSignals();
@@ -172,7 +172,13 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn)
172172
goto exit;
173173
}
174174
}
175-
break;
175+
else if (state != WAIT_TIMEOUT) {
176+
err = GetLastError();
177+
goto exit;
178+
}
179+
/* The console cancelled the read and flushed its input buffer,
180+
but no exception was raised. Start the read over. */
181+
continue;
176182
}
177183

178184
total_read += n_read;

0 commit comments

Comments
 (0)