Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a870e35

Browse files
author
Victor Stinner
committed
(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.
2 parents 80221ed + 52c950f commit a870e35

2 files changed

Lines changed: 53 additions & 45 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 3.2.1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #11650: PyOS_StdioReadline() retries fgets() if it was interrupted
14+
(EINTR), for example if the program is stopped with CTRL+z on Mac OS X. Patch
15+
written by Charles-Francois Natali.
16+
1317
- Issue #11395: io.FileIO().write() clamps the data length to 32,767 bytes on
1418
Windows if the file is a TTY to workaround a Windows bug. The Windows console
1519
returns an error (12: not enough space error) on writing into stdout if

Parser/myreadline.c

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,63 +36,67 @@ static int
3636
my_fgets(char *buf, int len, FILE *fp)
3737
{
3838
char *p;
39-
if (PyOS_InputHook != NULL)
40-
(void)(PyOS_InputHook)();
41-
errno = 0;
42-
p = fgets(buf, len, fp);
43-
if (p != NULL)
44-
return 0; /* No error */
39+
while (1) {
40+
if (PyOS_InputHook != NULL)
41+
(void)(PyOS_InputHook)();
42+
errno = 0;
43+
p = fgets(buf, len, fp);
44+
if (p != NULL)
45+
return 0; /* No error */
4546
#ifdef MS_WINDOWS
46-
/* In the case of a Ctrl+C or some other external event
47-
interrupting the operation:
48-
Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32
49-
error code (and feof() returns TRUE).
50-
Win9x: Ctrl+C seems to have no effect on fgets() returning
51-
early - the signal handler is called, but the fgets()
52-
only returns "normally" (ie, when Enter hit or feof())
53-
*/
54-
if (GetLastError()==ERROR_OPERATION_ABORTED) {
55-
/* Signals come asynchronously, so we sleep a brief
56-
moment before checking if the handler has been
57-
triggered (we cant just return 1 before the
58-
signal handler has been called, as the later
59-
signal may be treated as a separate interrupt).
47+
/* In the case of a Ctrl+C or some other external event
48+
interrupting the operation:
49+
Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32
50+
error code (and feof() returns TRUE).
51+
Win9x: Ctrl+C seems to have no effect on fgets() returning
52+
early - the signal handler is called, but the fgets()
53+
only returns "normally" (ie, when Enter hit or feof())
6054
*/
61-
Sleep(1);
62-
if (PyOS_InterruptOccurred()) {
63-
return 1; /* Interrupt */
55+
if (GetLastError()==ERROR_OPERATION_ABORTED) {
56+
/* Signals come asynchronously, so we sleep a brief
57+
moment before checking if the handler has been
58+
triggered (we cant just return 1 before the
59+
signal handler has been called, as the later
60+
signal may be treated as a separate interrupt).
61+
*/
62+
Sleep(1);
63+
if (PyOS_InterruptOccurred()) {
64+
return 1; /* Interrupt */
65+
}
66+
/* Either the sleep wasn't long enough (need a
67+
short loop retrying?) or not interrupted at all
68+
(in which case we should revisit the whole thing!)
69+
Logging some warning would be nice. assert is not
70+
viable as under the debugger, the various dialogs
71+
mean the condition is not true.
72+
*/
6473
}
65-
/* Either the sleep wasn't long enough (need a
66-
short loop retrying?) or not interrupted at all
67-
(in which case we should revisit the whole thing!)
68-
Logging some warning would be nice. assert is not
69-
viable as under the debugger, the various dialogs
70-
mean the condition is not true.
71-
*/
72-
}
7374
#endif /* MS_WINDOWS */
74-
if (feof(fp)) {
75-
return -1; /* EOF */
76-
}
75+
if (feof(fp)) {
76+
return -1; /* EOF */
77+
}
7778
#ifdef EINTR
78-
if (errno == EINTR) {
79-
int s;
79+
if (errno == EINTR) {
80+
int s;
8081
#ifdef WITH_THREAD
81-
PyEval_RestoreThread(_PyOS_ReadlineTState);
82+
PyEval_RestoreThread(_PyOS_ReadlineTState);
8283
#endif
83-
s = PyErr_CheckSignals();
84+
s = PyErr_CheckSignals();
8485
#ifdef WITH_THREAD
85-
PyEval_SaveThread();
86+
PyEval_SaveThread();
8687
#endif
87-
if (s < 0) {
88-
return 1;
88+
if (s < 0)
89+
return 1;
90+
/* try again */
91+
continue;
8992
}
90-
}
9193
#endif
92-
if (PyOS_InterruptOccurred()) {
93-
return 1; /* Interrupt */
94+
if (PyOS_InterruptOccurred()) {
95+
return 1; /* Interrupt */
96+
}
97+
return -2; /* Error */
9498
}
95-
return -2; /* Error */
99+
/* NOTREACHED */
96100
}
97101

98102

0 commit comments

Comments
 (0)