@@ -1975,13 +1975,14 @@ init_sys_streams(PyThreadState *tstate)
19751975
19761976
19771977static void
1978- _Py_FatalError_DumpTracebacks (int fd )
1978+ _Py_FatalError_DumpTracebacks (int fd , PyInterpreterState * interp ,
1979+ PyThreadState * tstate )
19791980{
19801981 fputc ('\n' , stderr );
19811982 fflush (stderr );
19821983
19831984 /* display the current Python stack */
1984- _Py_DumpTracebackThreads (fd , NULL , NULL );
1985+ _Py_DumpTracebackThreads (fd , interp , tstate );
19851986}
19861987
19871988/* Print the current exception (if an exception is set) with its traceback,
@@ -2079,10 +2080,39 @@ fatal_output_debug(const char *msg)
20792080}
20802081#endif
20812082
2083+
2084+ static void
2085+ fatal_error_dump_runtime (FILE * stream , _PyRuntimeState * runtime )
2086+ {
2087+ fprintf (stream , "Python runtime state: " );
2088+ if (runtime -> finalizing ) {
2089+ fprintf (stream , "finalizing (tstate=%p)" , runtime -> finalizing );
2090+ }
2091+ else if (runtime -> initialized ) {
2092+ fprintf (stream , "initialized" );
2093+ }
2094+ else if (runtime -> core_initialized ) {
2095+ fprintf (stream , "core initialized" );
2096+ }
2097+ else if (runtime -> preinitialized ) {
2098+ fprintf (stream , "preinitialized" );
2099+ }
2100+ else if (runtime -> preinitializing ) {
2101+ fprintf (stream , "preinitializing" );
2102+ }
2103+ else {
2104+ fprintf (stream , "unknown" );
2105+ }
2106+ fprintf (stream , "\n" );
2107+ fflush (stream );
2108+ }
2109+
2110+
20822111static void _Py_NO_RETURN
20832112fatal_error (const char * prefix , const char * msg , int status )
20842113{
2085- const int fd = fileno (stderr );
2114+ FILE * stream = stderr ;
2115+ const int fd = fileno (stream );
20862116 static int reentrant = 0 ;
20872117
20882118 if (reentrant ) {
@@ -2092,45 +2122,48 @@ fatal_error(const char *prefix, const char *msg, int status)
20922122 }
20932123 reentrant = 1 ;
20942124
2095- fprintf (stderr , "Fatal Python error: " );
2125+ fprintf (stream , "Fatal Python error: " );
20962126 if (prefix ) {
2097- fputs (prefix , stderr );
2098- fputs (": " , stderr );
2127+ fputs (prefix , stream );
2128+ fputs (": " , stream );
20992129 }
21002130 if (msg ) {
2101- fputs (msg , stderr );
2131+ fputs (msg , stream );
21022132 }
21032133 else {
2104- fprintf (stderr , "<message not set>" );
2134+ fprintf (stream , "<message not set>" );
21052135 }
2106- fputs ("\n" , stderr );
2107- fflush (stderr ); /* it helps in Windows debug build */
2136+ fputs ("\n" , stream );
2137+ fflush (stream ); /* it helps in Windows debug build */
21082138
2109- /* Check if the current thread has a Python thread state
2110- and holds the GIL */
2111- PyThreadState * tss_tstate = PyGILState_GetThisThreadState ();
2112- if (tss_tstate != NULL ) {
2113- PyThreadState * tstate = _PyThreadState_GET ();
2114- if (tss_tstate != tstate ) {
2115- /* The Python thread does not hold the GIL */
2116- tss_tstate = NULL ;
2117- }
2118- }
2119- else {
2120- /* Py_FatalError() has been called from a C thread
2121- which has no Python thread state. */
2139+ _PyRuntimeState * runtime = & _PyRuntime ;
2140+ fatal_error_dump_runtime (stream , runtime );
2141+
2142+ PyThreadState * tstate = _PyRuntimeState_GetThreadState (runtime );
2143+ PyInterpreterState * interp = NULL ;
2144+ if (tstate != NULL ) {
2145+ interp = tstate -> interp ;
21222146 }
2123- int has_tstate_and_gil = (tss_tstate != NULL );
21242147
2148+ /* Check if the current thread has a Python thread state
2149+ and holds the GIL.
2150+
2151+ tss_tstate is NULL if Py_FatalError() is called from a C thread which
2152+ has no Python thread state.
2153+
2154+ tss_tstate != tstate if the current Python thread does not hold the GIL.
2155+ */
2156+ PyThreadState * tss_tstate = PyGILState_GetThisThreadState ();
2157+ int has_tstate_and_gil = (tss_tstate != NULL && tss_tstate == tstate );
21252158 if (has_tstate_and_gil ) {
21262159 /* If an exception is set, print the exception with its traceback */
21272160 if (!_Py_FatalError_PrintExc (fd )) {
21282161 /* No exception is set, or an exception is set without traceback */
2129- _Py_FatalError_DumpTracebacks (fd );
2162+ _Py_FatalError_DumpTracebacks (fd , interp , tss_tstate );
21302163 }
21312164 }
21322165 else {
2133- _Py_FatalError_DumpTracebacks (fd );
2166+ _Py_FatalError_DumpTracebacks (fd , interp , tss_tstate );
21342167 }
21352168
21362169 /* The main purpose of faulthandler is to display the traceback.
0 commit comments