closes bpo-38156: Always handle interrupts in PyOS_StdioReadline. (GH-21569)
This consolidates the handling of my_fgets return values, so that interrupts are always handled, even if they come after EOF. I believe PyOS_StdioReadline is still buggy in that I/O errors will not result in a proper Python exception being set. However, that is a separate issue.
This commit is contained in:
parent
f6a16e8a82
commit
a74eea238f
|
@ -0,0 +1 @@
|
|||
Handle interrupts that come after EOF correctly in ``PyOS_StdioReadline``.
|
|
@ -291,37 +291,16 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
|||
}
|
||||
#endif
|
||||
|
||||
n = 100;
|
||||
p = (char *)PyMem_RawMalloc(n);
|
||||
if (p == NULL) {
|
||||
PyEval_RestoreThread(tstate);
|
||||
PyErr_NoMemory();
|
||||
PyEval_SaveThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fflush(sys_stdout);
|
||||
if (prompt) {
|
||||
fprintf(stderr, "%s", prompt);
|
||||
}
|
||||
fflush(stderr);
|
||||
|
||||
switch (my_fgets(tstate, p, (int)n, sys_stdin)) {
|
||||
case 0: /* Normal case */
|
||||
break;
|
||||
case 1: /* Interrupt */
|
||||
PyMem_RawFree(p);
|
||||
return NULL;
|
||||
case -1: /* EOF */
|
||||
case -2: /* Error */
|
||||
default: /* Shouldn't happen */
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
n = strlen(p);
|
||||
while (n > 0 && p[n-1] != '\n') {
|
||||
size_t incr = n+2;
|
||||
n = 0;
|
||||
p = NULL;
|
||||
do {
|
||||
size_t incr = (n > 0) ? n + 2 : 100;
|
||||
if (incr > INT_MAX) {
|
||||
PyMem_RawFree(p);
|
||||
PyEval_RestoreThread(tstate);
|
||||
|
@ -329,7 +308,6 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
|||
PyEval_SaveThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pr = (char *)PyMem_RawRealloc(p, n + incr);
|
||||
if (pr == NULL) {
|
||||
PyMem_RawFree(p);
|
||||
|
@ -339,12 +317,18 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
|||
return NULL;
|
||||
}
|
||||
p = pr;
|
||||
|
||||
if (my_fgets(tstate, p+n, (int)incr, sys_stdin) != 0) {
|
||||
int err = my_fgets(tstate, p + n, incr, sys_stdin);
|
||||
if (err == 1) {
|
||||
// Interrupt
|
||||
PyMem_RawFree(p);
|
||||
return NULL;
|
||||
} else if (err != 0) {
|
||||
// EOF or error
|
||||
p[n] = '\0';
|
||||
break;
|
||||
}
|
||||
n += strlen(p+n);
|
||||
}
|
||||
n += strlen(p + n);
|
||||
} while (p[n-1] != '\n');
|
||||
|
||||
pr = (char *)PyMem_RawRealloc(p, n+1);
|
||||
if (pr == NULL) {
|
||||
|
|
Loading…
Reference in New Issue