summaryrefslogtreecommitdiff
path: root/Parser/myreadline.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-04-09 15:59:25 +0200
committerVictor Stinner <victor.stinner@haypocalc.com>2011-04-09 15:59:25 +0200
commita870e35a7dff135a9c1075ab2ea068c9f7b2f379 (patch)
treee75606dc5dc040c4f3695db93000847e2ff97aec /Parser/myreadline.c
parent80221ed0c0f3c73ee13c5d2c64a9b0273933a0ce (diff)
parent52c950f229199fa14bd75e1709183d0b08e90182 (diff)
downloadcpython-git-a870e35a7dff135a9c1075ab2ea068c9f7b2f379.tar.gz
(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/myreadline.c')
-rw-r--r--Parser/myreadline.c94
1 files changed, 49 insertions, 45 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index ecb4701b89..50802c3156 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 */
}