diff options
author | Victor Stinner <vstinner@python.org> | 2020-06-03 12:39:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-03 12:39:59 (GMT) |
commit | fa7ab6aa0f9a4f695e5525db5a113cd21fa93787 (patch) | |
tree | db9c9a9fc6908662ed752d6617a719cc566f155f /Parser | |
parent | 18a90248fdd92b27098cc4db773686a2d10a4d24 (diff) | |
download | cpython-fa7ab6aa0f9a4f695e5525db5a113cd21fa93787.zip cpython-fa7ab6aa0f9a4f695e5525db5a113cd21fa93787.tar.gz cpython-fa7ab6aa0f9a4f695e5525db5a113cd21fa93787.tar.bz2 |
bpo-40826: Add _PyOS_InterruptOccurred(tstate) function (GH-20599)
my_fgets() now calls _PyOS_InterruptOccurred(tstate) to check for
pending signals, rather calling PyOS_InterruptOccurred().
my_fgets() is called with the GIL released, whereas
PyOS_InterruptOccurred() must be called with the GIL held.
test_repl: use text=True and avoid SuppressCrashReport in
test_multiline_string_parsing().
Fix my_fgets() on Windows: fgets(fp) does crash if fileno(fp) is closed.
Diffstat (limited to 'Parser')
-rw-r--r-- | Parser/myreadline.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c index d2787f0..2dd3623 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -24,14 +24,23 @@ static PyThread_type_lock _PyOS_ReadlineLock = NULL; int (*PyOS_InputHook)(void) = NULL; /* This function restarts a fgets() after an EINTR error occurred - except if PyOS_InterruptOccurred() returns true. */ + except if _PyOS_InterruptOccurred() returns true. */ static int my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp) { #ifdef MS_WINDOWS - HANDLE hInterruptEvent; + HANDLE handle; + _Py_BEGIN_SUPPRESS_IPH + handle = (HANDLE)_get_osfhandle(fileno(fp)); + _Py_END_SUPPRESS_IPH + + /* bpo-40826: fgets(fp) does crash if fileno(fp) is closed */ + if (handle == INVALID_HANDLE_VALUE) { + return -1; /* EOF */ + } #endif + while (1) { if (PyOS_InputHook != NULL) { (void)(PyOS_InputHook)(); @@ -60,7 +69,7 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp) through to check for EOF. */ if (GetLastError()==ERROR_OPERATION_ABORTED) { - hInterruptEvent = _PyOS_SigintEvent(); + HANDLE hInterruptEvent = _PyOS_SigintEvent(); switch (WaitForSingleObjectEx(hInterruptEvent, 10, FALSE)) { case WAIT_OBJECT_0: ResetEvent(hInterruptEvent); @@ -90,7 +99,7 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp) } #endif - if (PyOS_InterruptOccurred()) { + if (_PyOS_InterruptOccurred(tstate)) { return 1; /* Interrupt */ } return -2; /* Error */ |