@@ -2587,28 +2587,75 @@ err_input(perrdetail *err)
25872587 }
25882588}
25892589
2590+ /* Print the current exception (if an exception is set) with its traceback,
2591+ * or display the current Python stack.
2592+ *
2593+ * Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
2594+ * called on catastrophic cases. */
2595+
2596+ static void
2597+ _Py_PrintFatalError (int fd )
2598+ {
2599+ PyObject * exception , * v , * tb ;
2600+ int has_tb ;
2601+ PyThreadState * tstate ;
2602+
2603+ PyErr_Fetch (& exception , & v , & tb );
2604+ if (exception == NULL ) {
2605+ /* No current exception */
2606+ goto display_stack ;
2607+ }
2608+
2609+ PyErr_NormalizeException (& exception , & v , & tb );
2610+ if (tb == NULL ) {
2611+ tb = Py_None ;
2612+ Py_INCREF (tb );
2613+ }
2614+ PyException_SetTraceback (v , tb );
2615+ if (exception == NULL ) {
2616+ /* too bad, PyErr_NormalizeException() failed */
2617+ goto display_stack ;
2618+ }
2619+
2620+ has_tb = (tb != NULL && tb != Py_None );
2621+ PyErr_Display (exception , v , tb );
2622+ Py_XDECREF (exception );
2623+ Py_XDECREF (v );
2624+ Py_XDECREF (tb );
2625+ if (has_tb )
2626+ return ;
2627+
2628+ display_stack :
2629+ /* PyGILState_GetThisThreadState() works even if the GIL was released */
2630+ tstate = PyGILState_GetThisThreadState ();
2631+ if (tstate == NULL ) {
2632+ /* _Py_DumpTracebackThreads() requires the thread state to display
2633+ * frames */
2634+ return ;
2635+ }
2636+
2637+ fputc ('\n' , stderr );
2638+ fflush (stderr );
2639+
2640+ /* display the current Python stack */
2641+ _Py_DumpTracebackThreads (fd , tstate -> interp , tstate );
2642+ }
2643+
25902644/* Print fatal error message and abort */
25912645
25922646void
25932647Py_FatalError (const char * msg )
25942648{
25952649 const int fd = fileno (stderr );
2596- PyThreadState * tstate ;
25972650
25982651 fprintf (stderr , "Fatal Python error: %s\n" , msg );
25992652 fflush (stderr ); /* it helps in Windows debug build */
2600- if (PyErr_Occurred ()) {
2601- PyErr_PrintEx (0 );
2602- }
2603- else {
2604- tstate = _Py_atomic_load_relaxed (& _PyThreadState_Current );
2605- if (tstate != NULL ) {
2606- fputc ('\n' , stderr );
2607- fflush (stderr );
2608- _Py_DumpTracebackThreads (fd , tstate -> interp , tstate );
2609- }
2610- _PyFaulthandler_Fini ();
2611- }
2653+
2654+ _Py_PrintFatalError (fd );
2655+
2656+ /* 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. */
2658+ _PyFaulthandler_Fini ();
26122659
26132660#ifdef MS_WINDOWS
26142661 {
0 commit comments