Mailing List Archive

closes bpo-38156: Always handle interrupts in PyOS_StdioReadline. (GH-21569)
https://github.com/python/cpython/commit/a74eea238f5baba15797e2e8b570d153bc8690a7
commit: a74eea238f5baba15797e2e8b570d153bc8690a7
branch: master
author: Benjamin Peterson <benjamin@python.org>
committer: GitHub <noreply@github.com>
date: 2020-07-28T19:57:12-05:00
summary:

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.

files:
A Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
M Parser/myreadline.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst b/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
new file mode 100644
index 0000000000000..254d13cf3ed3a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
@@ -0,0 +1 @@
+Handle interrupts that come after EOF correctly in ``PyOS_StdioReadline``.
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index 2dd362321aaf3..a49c9d892dda9 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -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) {

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins
closes bpo-38156: Always handle interrupts in PyOS_StdioReadline. (GH-21569) [ In reply to ]
https://github.com/python/cpython/commit/7cfede6859586f77f786bda56af4698ae2245f56
commit: 7cfede6859586f77f786bda56af4698ae2245f56
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
committer: GitHub <noreply@github.com>
date: 2020-07-28T18:16:19-07:00
summary:

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.
(cherry picked from commit a74eea238f5baba15797e2e8b570d153bc8690a7)

Co-authored-by: Benjamin Peterson <benjamin@python.org>

files:
A Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
M Parser/myreadline.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst b/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
new file mode 100644
index 0000000000000..254d13cf3ed3a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-07-20-17-01-17.bpo-38156.ptcdRy.rst
@@ -0,0 +1 @@
+Handle interrupts that come after EOF correctly in ``PyOS_StdioReadline``.
diff --git a/Parser/myreadline.c b/Parser/myreadline.c
index d7ed357faa383..29b254f771f16 100644
--- a/Parser/myreadline.c
+++ b/Parser/myreadline.c
@@ -292,37 +292,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);
@@ -330,7 +309,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);
@@ -340,12 +318,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) {

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins