changeset: 95160:da252f12352a branch: 3.4 parent: 95153:efb2c9ac2f88 user: Victor Stinner date: Tue Mar 24 13:44:35 2015 +0100 files: Python/pythonrun.c description: 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. diff -r efb2c9ac2f88 -r da252f12352a Python/pythonrun.c --- a/Python/pythonrun.c Tue Mar 24 11:24:06 2015 +0100 +++ b/Python/pythonrun.c Tue Mar 24 13:44:35 2015 +0100 @@ -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