[Python-checkins] closes bpo-38156: Always handle interrupts in PyOS_StdioReadline. (GH-21569)

Miss Islington (bot) webhook-mailer at python.org
Tue Jul 28 21:16:27 EDT 2020


https://github.com/python/cpython/commit/7cfede6859586f77f786bda56af4698ae2245f56
commit: 7cfede6859586f77f786bda56af4698ae2245f56
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at 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 at 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) {



More information about the Python-checkins mailing list