Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ec4f959

Browse files
committed
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.
1 parent 0e98a76 commit ec4f959

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

Python/pythonrun.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ Py_Finalize(void)
586586
_Py_Finalizing = tstate;
587587
initialized = 0;
588588

589-
/* Flush stdout+stderr */
589+
/* Flush sys.stdout and sys.stderr */
590590
flush_std_files();
591591

592592
/* Disable signal handling */
@@ -615,7 +615,7 @@ Py_Finalize(void)
615615
/* Destroy all modules */
616616
PyImport_Cleanup();
617617

618-
/* Flush stdout+stderr (again, in case more was printed) */
618+
/* Flush sys.stdout and sys.stderr (again, in case more was printed) */
619619
flush_std_files();
620620

621621
/* Collect final garbage. This disposes of cycles created by
@@ -2596,6 +2596,7 @@ err_input(perrdetail *err)
25962596
static void
25972597
_Py_PrintFatalError(int fd)
25982598
{
2599+
PyObject *ferr, *res;
25992600
PyObject *exception, *v, *tb;
26002601
int has_tb;
26012602
PyThreadState *tstate;
@@ -2606,14 +2607,21 @@ _Py_PrintFatalError(int fd)
26062607
goto display_stack;
26072608
}
26082609

2610+
ferr = _PySys_GetObjectId(&PyId_stderr);
2611+
if (ferr == NULL || ferr == Py_None) {
2612+
/* sys.stderr is not set yet or set to None,
2613+
no need to try to display the exception */
2614+
goto display_stack;
2615+
}
2616+
26092617
PyErr_NormalizeException(&exception, &v, &tb);
26102618
if (tb == NULL) {
26112619
tb = Py_None;
26122620
Py_INCREF(tb);
26132621
}
26142622
PyException_SetTraceback(v, tb);
26152623
if (exception == NULL) {
2616-
/* too bad, PyErr_NormalizeException() failed */
2624+
/* PyErr_NormalizeException() failed */
26172625
goto display_stack;
26182626
}
26192627

@@ -2622,6 +2630,14 @@ _Py_PrintFatalError(int fd)
26222630
Py_XDECREF(exception);
26232631
Py_XDECREF(v);
26242632
Py_XDECREF(tb);
2633+
2634+
/* sys.stderr may be buffered: call sys.stderr.flush() */
2635+
res = _PyObject_CallMethodId(ferr, &PyId_flush, "");
2636+
if (res == NULL)
2637+
PyErr_Clear();
2638+
else
2639+
Py_DECREF(res);
2640+
26252641
if (has_tb)
26262642
return;
26272643

@@ -2651,10 +2667,16 @@ Py_FatalError(const char *msg)
26512667
fprintf(stderr, "Fatal Python error: %s\n", msg);
26522668
fflush(stderr); /* it helps in Windows debug build */
26532669

2670+
/* Print the exception (if an exception is set) with its traceback,
2671+
* or display the current Python stack. */
26542672
_Py_PrintFatalError(fd);
26552673

2674+
/* Flush sys.stdout and sys.stderr */
2675+
flush_std_files();
2676+
26562677
/* The main purpose of faulthandler is to display the traceback. We already
2657-
* did our best to display it. So faulthandler can now be disabled. */
2678+
* did our best to display it. So faulthandler can now be disabled.
2679+
* (Don't trigger it on abort().) */
26582680
_PyFaulthandler_Fini();
26592681

26602682
#ifdef MS_WINDOWS

0 commit comments

Comments
 (0)