bpo-36829: sys.excepthook and sys.unraisablehook flush (GH-13620)
authorVictor Stinner <vstinner@redhat.com>
Tue, 28 May 2019 14:01:17 +0000 (16:01 +0200)
committerGitHub <noreply@github.com>
Tue, 28 May 2019 14:01:17 +0000 (16:01 +0200)
sys.excepthook() and sys.unraisablehook() now explicitly flush the
file (usually sys.stderr).

If file.flush() fails, sys.excepthook() silently ignores the error,
whereas sys.unraisablehook() logs the new exception.

Python/errors.c
Python/pythonrun.c

index bd33d4d340f6683f4e751644abb833bb7d0c2188..8a94afdd8c41015314b4c0b2f781abe2f00183c6 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 
 _Py_IDENTIFIER(builtins);
 _Py_IDENTIFIER(stderr);
+_Py_IDENTIFIER(flush);
 
 
 /* Forward declarations */
@@ -1254,6 +1255,14 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
     if (PyFile_WriteString("\n", file) < 0) {
         return -1;
     }
+
+    /* Explicitly call file.flush() */
+    PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
+    if (!res) {
+        return -1;
+    }
+    Py_DECREF(res);
+
     return 0;
 }
 
index ba1d1cf02f25846812604de6b2ce73001c0000f7..ace9f2f9874e748ca74cc858690fcad1d5837ac7 100644 (file)
@@ -978,6 +978,16 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t
     }
     print_exception_recursive(file, value, seen);
     Py_XDECREF(seen);
+
+    /* Call file.flush() */
+    PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
+    if (!res) {
+        /* Silently ignore file.flush() error */
+        PyErr_Clear();
+    }
+    else {
+        Py_DECREF(res);
+    }
 }
 
 void