[Python-checkins] cpython (3.4): Issue #23571: Py_FatalError() now tries to flush sys.stdout and sys.stderr

victor.stinner python-checkins at python.org
Tue Mar 24 14:07:22 CET 2015


https://hg.python.org/cpython/rev/da252f12352a
changeset:   95160:da252f12352a
branch:      3.4
parent:      95153:efb2c9ac2f88
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Mar 24 13:44:35 2015 +0100
summary:
  Issue #23571: Py_FatalError() now tries to flush sys.stdout and sys.stderr

It should help to see exceptions when stderr if buffered: PyErr_Display() calls
sys.stderr.write(), it doesn't write into stderr file descriptor directly.

files:
  Python/pythonrun.c |  30 ++++++++++++++++++++++++++----
  1 files changed, 26 insertions(+), 4 deletions(-)


diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -586,7 +586,7 @@
     _Py_Finalizing = tstate;
     initialized = 0;
 
-    /* Flush stdout+stderr */
+    /* Flush sys.stdout and sys.stderr */
     flush_std_files();
 
     /* Disable signal handling */
@@ -615,7 +615,7 @@
     /* Destroy all modules */
     PyImport_Cleanup();
 
-    /* Flush stdout+stderr (again, in case more was printed) */
+    /* Flush sys.stdout and sys.stderr (again, in case more was printed) */
     flush_std_files();
 
     /* Collect final garbage.  This disposes of cycles created by
@@ -2596,6 +2596,7 @@
 static void
 _Py_PrintFatalError(int fd)
 {
+    PyObject *ferr, *res;
     PyObject *exception, *v, *tb;
     int has_tb;
     PyThreadState *tstate;
@@ -2606,6 +2607,13 @@
         goto display_stack;
     }
 
+    ferr = _PySys_GetObjectId(&PyId_stderr);
+    if (ferr == NULL || ferr == Py_None) {
+        /* sys.stderr is not set yet or set to None,
+           no need to try to display the exception */
+        goto display_stack;
+    }
+
     PyErr_NormalizeException(&exception, &v, &tb);
     if (tb == NULL) {
         tb = Py_None;
@@ -2613,7 +2621,7 @@
     }
     PyException_SetTraceback(v, tb);
     if (exception == NULL) {
-        /* too bad, PyErr_NormalizeException() failed */
+        /* PyErr_NormalizeException() failed */
         goto display_stack;
     }
 
@@ -2622,6 +2630,14 @@
     Py_XDECREF(exception);
     Py_XDECREF(v);
     Py_XDECREF(tb);
+
+    /* sys.stderr may be buffered: call sys.stderr.flush() */
+    res = _PyObject_CallMethodId(ferr, &PyId_flush, "");
+    if (res == NULL)
+        PyErr_Clear();
+    else
+        Py_DECREF(res);
+
     if (has_tb)
         return;
 
@@ -2651,10 +2667,16 @@
     fprintf(stderr, "Fatal Python error: %s\n", msg);
     fflush(stderr); /* it helps in Windows debug build */
 
+    /* Print the exception (if an exception is set) with its traceback,
+     * or display the current Python stack. */
     _Py_PrintFatalError(fd);
 
+    /* Flush sys.stdout and sys.stderr */
+    flush_std_files();
+
     /* The main purpose of faulthandler is to display the traceback. We already
-     * did our best to display it. So faulthandler can now be disabled. */
+     * did our best to display it. So faulthandler can now be disabled.
+     * (Don't trigger it on abort().) */
     _PyFaulthandler_Fini();
 
 #ifdef MS_WINDOWS

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list