From: Victor Stinner Date: Sat, 9 Apr 2011 13:59:25 +0000 (+0200) Subject: (Merge 3.1) Issue #11650: PyOS_StdioReadline() retries fgets() if it was X-Git-Tag: v3.2.1b1~161 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a870e35a7dff135a9c1075ab2ea068c9f7b2f379;p=python (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. --- a870e35a7dff135a9c1075ab2ea068c9f7b2f379 diff --cc Misc/NEWS index 80d46ed117,895e50d6fa..39faa4b475 --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -10,20 -10,13 +10,24 @@@ What's New in Python 3.2.1 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 #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 #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. diff --cc Parser/myreadline.c index ecb4701b89,7166fc1d01..50802c3156 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@@ -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 */ }