Kaydet (Commit) e0deff31 authored tarafından Victor Stinner's avatar Victor Stinner

(Merge 3.4) 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.
...@@ -546,7 +546,7 @@ Py_Finalize(void) ...@@ -546,7 +546,7 @@ Py_Finalize(void)
_Py_Finalizing = tstate; _Py_Finalizing = tstate;
initialized = 0; initialized = 0;
/* Flush stdout+stderr */ /* Flush sys.stdout and sys.stderr */
flush_std_files(); flush_std_files();
/* Disable signal handling */ /* Disable signal handling */
...@@ -575,7 +575,7 @@ Py_Finalize(void) ...@@ -575,7 +575,7 @@ Py_Finalize(void)
/* Destroy all modules */ /* Destroy all modules */
PyImport_Cleanup(); 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(); flush_std_files();
/* Collect final garbage. This disposes of cycles created by /* Collect final garbage. This disposes of cycles created by
...@@ -1253,6 +1253,7 @@ initstdio(void) ...@@ -1253,6 +1253,7 @@ initstdio(void)
static void static void
_Py_PrintFatalError(int fd) _Py_PrintFatalError(int fd)
{ {
PyObject *ferr, *res;
PyObject *exception, *v, *tb; PyObject *exception, *v, *tb;
int has_tb; int has_tb;
PyThreadState *tstate; PyThreadState *tstate;
...@@ -1263,6 +1264,13 @@ _Py_PrintFatalError(int fd) ...@@ -1263,6 +1264,13 @@ _Py_PrintFatalError(int fd)
goto display_stack; 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); PyErr_NormalizeException(&exception, &v, &tb);
if (tb == NULL) { if (tb == NULL) {
tb = Py_None; tb = Py_None;
...@@ -1270,7 +1278,7 @@ _Py_PrintFatalError(int fd) ...@@ -1270,7 +1278,7 @@ _Py_PrintFatalError(int fd)
} }
PyException_SetTraceback(v, tb); PyException_SetTraceback(v, tb);
if (exception == NULL) { if (exception == NULL) {
/* too bad, PyErr_NormalizeException() failed */ /* PyErr_NormalizeException() failed */
goto display_stack; goto display_stack;
} }
...@@ -1279,6 +1287,14 @@ _Py_PrintFatalError(int fd) ...@@ -1279,6 +1287,14 @@ _Py_PrintFatalError(int fd)
Py_XDECREF(exception); Py_XDECREF(exception);
Py_XDECREF(v); Py_XDECREF(v);
Py_XDECREF(tb); 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) if (has_tb)
return; return;
...@@ -1307,10 +1323,16 @@ Py_FatalError(const char *msg) ...@@ -1307,10 +1323,16 @@ Py_FatalError(const char *msg)
fprintf(stderr, "Fatal Python error: %s\n", msg); fprintf(stderr, "Fatal Python error: %s\n", msg);
fflush(stderr); /* it helps in Windows debug build */ 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); _Py_PrintFatalError(fd);
/* Flush sys.stdout and sys.stderr */
flush_std_files();
/* The main purpose of faulthandler is to display the traceback. We already /* 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(); _PyFaulthandler_Fini();
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment