diff options
author | Victor Stinner <victor.stinner@haypocalc.com> | 2011-04-09 13:59:25 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@haypocalc.com> | 2011-04-09 13:59:25 (GMT) |
commit | a870e35a7dff135a9c1075ab2ea068c9f7b2f379 (patch) | |
tree | e75606dc5dc040c4f3695db93000847e2ff97aec /Parser | |
parent | 80221ed0c0f3c73ee13c5d2c64a9b0273933a0ce (diff) | |
parent | 52c950f229199fa14bd75e1709183d0b08e90182 (diff) | |
download | cpython-a870e35a7dff135a9c1075ab2ea068c9f7b2f379.zip cpython-a870e35a7dff135a9c1075ab2ea068c9f7b2f379.tar.gz cpython-a870e35a7dff135a9c1075ab2ea068c9f7b2f379.tar.bz2 |
(Merge 3.1) Issue #11650: PyOS_StdioReadline() retries fgets() if it was
interrupted (EINTR), for example if the program is stopped with CTRL+z on Mac
OS X. Patch written by Charles-Francois Natali.
Diffstat (limited to 'Parser')
-rw-r--r-- | Parser/myreadline.c | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c index ecb4701..50802c3 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -36,63 +36,67 @@ static int my_fgets(char *buf, int len, FILE *fp) { char *p; - if (PyOS_InputHook != NULL) - (void)(PyOS_InputHook)(); - errno = 0; - p = fgets(buf, len, fp); - if (p != NULL) - return 0; /* No error */ + while (1) { + if (PyOS_InputHook != NULL) + (void)(PyOS_InputHook)(); + errno = 0; + p = fgets(buf, len, fp); + if (p != NULL) + return 0; /* No error */ #ifdef MS_WINDOWS - /* In the case of a Ctrl+C or some other external event - interrupting the operation: - Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 - error code (and feof() returns TRUE). - Win9x: Ctrl+C seems to have no effect on fgets() returning - early - the signal handler is called, but the fgets() - only returns "normally" (ie, when Enter hit or feof()) - */ - if (GetLastError()==ERROR_OPERATION_ABORTED) { - /* Signals come asynchronously, so we sleep a brief - moment before checking if the handler has been - triggered (we cant just return 1 before the - signal handler has been called, as the later - signal may be treated as a separate interrupt). + /* In the case of a Ctrl+C or some other external event + interrupting the operation: + Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 + error code (and feof() returns TRUE). + Win9x: Ctrl+C seems to have no effect on fgets() returning + early - the signal handler is called, but the fgets() + only returns "normally" (ie, when Enter hit or feof()) */ - Sleep(1); - if (PyOS_InterruptOccurred()) { - return 1; /* Interrupt */ + if (GetLastError()==ERROR_OPERATION_ABORTED) { + /* Signals come asynchronously, so we sleep a brief + moment before checking if the handler has been + triggered (we cant just return 1 before the + signal handler has been called, as the later + signal may be treated as a separate interrupt). + */ + Sleep(1); + if (PyOS_InterruptOccurred()) { + return 1; /* Interrupt */ + } + /* Either the sleep wasn't long enough (need a + short loop retrying?) or not interrupted at all + (in which case we should revisit the whole thing!) + Logging some warning would be nice. assert is not + viable as under the debugger, the various dialogs + mean the condition is not true. + */ } - /* Either the sleep wasn't long enough (need a - short loop retrying?) or not interrupted at all - (in which case we should revisit the whole thing!) - Logging some warning would be nice. assert is not - viable as under the debugger, the various dialogs - mean the condition is not true. - */ - } #endif /* MS_WINDOWS */ - if (feof(fp)) { - return -1; /* EOF */ - } + if (feof(fp)) { + return -1; /* EOF */ + } #ifdef EINTR - if (errno == EINTR) { - int s; + if (errno == EINTR) { + int s; #ifdef WITH_THREAD - PyEval_RestoreThread(_PyOS_ReadlineTState); + PyEval_RestoreThread(_PyOS_ReadlineTState); #endif - s = PyErr_CheckSignals(); + s = PyErr_CheckSignals(); #ifdef WITH_THREAD - PyEval_SaveThread(); + PyEval_SaveThread(); #endif - if (s < 0) { - return 1; + if (s < 0) + return 1; + /* try again */ + continue; } - } #endif - if (PyOS_InterruptOccurred()) { - return 1; /* Interrupt */ + if (PyOS_InterruptOccurred()) { + return 1; /* Interrupt */ + } + return -2; /* Error */ } - return -2; /* Error */ + /* NOTREACHED */ } |