(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.
This commit is contained in:
commit
e0deff31d3
|
@ -546,7 +546,7 @@ Py_Finalize(void)
|
|||
_Py_Finalizing = tstate;
|
||||
initialized = 0;
|
||||
|
||||
/* Flush stdout+stderr */
|
||||
/* Flush sys.stdout and sys.stderr */
|
||||
flush_std_files();
|
||||
|
||||
/* Disable signal handling */
|
||||
|
@ -575,7 +575,7 @@ Py_Finalize(void)
|
|||
/* 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
|
||||
|
@ -1253,6 +1253,7 @@ initstdio(void)
|
|||
static void
|
||||
_Py_PrintFatalError(int fd)
|
||||
{
|
||||
PyObject *ferr, *res;
|
||||
PyObject *exception, *v, *tb;
|
||||
int has_tb;
|
||||
PyThreadState *tstate;
|
||||
|
@ -1263,6 +1264,13 @@ _Py_PrintFatalError(int fd)
|
|||
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;
|
||||
|
@ -1270,7 +1278,7 @@ _Py_PrintFatalError(int fd)
|
|||
}
|
||||
PyException_SetTraceback(v, tb);
|
||||
if (exception == NULL) {
|
||||
/* too bad, PyErr_NormalizeException() failed */
|
||||
/* PyErr_NormalizeException() failed */
|
||||
goto display_stack;
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1287,14 @@ _Py_PrintFatalError(int fd)
|
|||
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;
|
||||
|
||||
|
@ -1307,10 +1323,16 @@ Py_FatalError(const char *msg)
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue