@@ -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)
25962596static 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