]> granicus.if.org Git - python/commitdiff
(Merge 3.1) Issue #11650: PyOS_StdioReadline() retries fgets() if it was
authorVictor Stinner <victor.stinner@haypocalc.com>
Sat, 9 Apr 2011 14:09:08 +0000 (16:09 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Sat, 9 Apr 2011 14:09:08 +0000 (16:09 +0200)
interrupted (EINTR), for example if the program is stopped with CTRL+z on Mac
OS X. Patch written by Charles-Francois Natali.

Misc/NEWS
Parser/myreadline.c

index f460127bdff99a48bdd5db7345b81921369e8d7f..a4b32ae3e03cd05838c0464fd1f6fdd37c980917 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,10 @@ What's New in Python 2.7.2?
 Core and Builtins
 -----------------
 
+- 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.
+
 - Issue #11144: Ensure that int(a_float) returns an int whenever possible.
   Previously, there were some corner cases where a long was returned even
   though the result was within the range of an int.
index 6d90d2005943de45c1d4a62dce01922ff590a658..8a76e0c23b4cc889d93b25baa841dfaeb2558121 100644 (file)
@@ -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 */
 }