]> 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 13:59:25 +0000 (15:59 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Sat, 9 Apr 2011 13:59:25 +0000 (15:59 +0200)
interrupted (EINTR), for example if the program is stopped with CTRL+z on Mac
OS X. Patch written by Charles-Francois Natali.

1  2 
Misc/NEWS
Parser/myreadline.c

diff --cc Misc/NEWS
index 80d46ed117af8c6e91a6f1ea3ef1855688027ec7,895e50d6fa416004c7e3a9db06f2d27c6cf9929d..39faa4b475b18b03028f554f165d9fd6b8857216
+++ b/Misc/NEWS
@@@ -10,20 -10,13 +10,24 @@@ What's New in Python 3.2.1
  Core and Builtins
  -----------------
  
 -- Issue #8651: PyArg_Parse*() functions raise an OverflowError if the file
 -  doesn't have PY_SSIZE_T_CLEAN define and the size doesn't fit in an int
 -  (length bigger than 2^31-1 bytes).
+ - 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 #11395: io.FileIO().write() clamps the data length to 32,767 bytes on
 +  Windows if the file is a TTY to workaround a Windows bug. The Windows console
 +  returns an error (12: not enough space error) on writing into stdout if
 +  stdout mode is binary and the length is greater than 66,000 bytes (or less,
 +  depending on heap usage).
 +
 +- Issue #11320: fix bogus memory management in Modules/getpath.c, leading to
 +  a possible crash when calling Py_SetPath().
 +
 +- Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)".
 +
 +- Issue #11432: A bug was introduced in subprocess.Popen on posix systems with
 +  3.2.0 where the stdout or stderr file descriptor being the same as the stdin
 +  file descriptor would raise an exception. webbrowser.open would fail. fixed.
  
  - Issue #11450: Don't truncate hg version info in Py_GetBuildInfo() when
    there are many tags (e.g. when using mq).  Patch by Nadeem Vawda.
index ecb4701b89a827d2fac919cea6b3bb80e87c9fe8,7166fc1d010611fb663e25144fdb4f9f712fe7e4..50802c31564a78f6ac9cc0c0b771b896c9fef330
@@@ -36,63 -36,67 +36,67 @@@ static in
  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 */
++          /* try again */
+             continue;
          }
-     }
  #endif
-     if (PyOS_InterruptOccurred()) {
-         return 1; /* Interrupt */
+         if (PyOS_InterruptOccurred()) {
+             return 1; /* Interrupt */
+         }
+         return -2; /* Error */
      }
-     return -2; /* Error */
+     /* NOTREACHED */
  }