summaryrefslogtreecommitdiffstats
path: root/Parser
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-04-09 14:09:08 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-04-09 14:09:08 (GMT)
commit5de51ac4c00f36d0caa5bd99d0bfa0fdbad35627 (patch)
tree1949256074bc2feea586bf94e929c5984cea3cca /Parser
parent5dbca9cc3f92167e686f4e4a44eef25a28f2977d (diff)
downloadcpython-5de51ac4c00f36d0caa5bd99d0bfa0fdbad35627.zip
cpython-5de51ac4c00f36d0caa5bd99d0bfa0fdbad35627.tar.gz
cpython-5de51ac4c00f36d0caa5bd99d0bfa0fdbad35627.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.c94
1 files changed, 49 insertions, 45 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 6d90d20..8a76e0c 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -40,63 +40,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 */
}