@@ -719,11 +719,15 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)
719719 }
720720 _PyRuntimeState * runtime = & _PyRuntime ;
721721
722- if (runtime -> pre_initialized ) {
722+ if (runtime -> preinitialized ) {
723723 /* If it's already configured: ignored the new configuration */
724724 return _PyStatus_OK ();
725725 }
726726
727+ /* Note: preinitialized remains 1 on error, it is only set to 0
728+ at exit on success. */
729+ runtime -> preinitializing = 1 ;
730+
727731 PyPreConfig config ;
728732 _PyPreConfig_InitFromPreConfig (& config , src_config );
729733
@@ -737,7 +741,8 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)
737741 return status ;
738742 }
739743
740- runtime -> pre_initialized = 1 ;
744+ runtime -> preinitializing = 0 ;
745+ runtime -> preinitialized = 1 ;
741746 return _PyStatus_OK ();
742747}
743748
@@ -777,7 +782,7 @@ _Py_PreInitializeFromConfig(const PyConfig *config,
777782 }
778783 _PyRuntimeState * runtime = & _PyRuntime ;
779784
780- if (runtime -> pre_initialized ) {
785+ if (runtime -> preinitialized ) {
781786 /* Already initialized: do nothing */
782787 return _PyStatus_OK ();
783788 }
@@ -1961,13 +1966,14 @@ init_sys_streams(PyInterpreterState *interp)
19611966
19621967
19631968static void
1964- _Py_FatalError_DumpTracebacks (int fd )
1969+ _Py_FatalError_DumpTracebacks (int fd , PyInterpreterState * interp ,
1970+ PyThreadState * tstate )
19651971{
19661972 fputc ('\n' , stderr );
19671973 fflush (stderr );
19681974
19691975 /* display the current Python stack */
1970- _Py_DumpTracebackThreads (fd , NULL , NULL );
1976+ _Py_DumpTracebackThreads (fd , interp , tstate );
19711977}
19721978
19731979/* Print the current exception (if an exception is set) with its traceback,
@@ -2062,10 +2068,39 @@ fatal_output_debug(const char *msg)
20622068}
20632069#endif
20642070
2071+
2072+ static void
2073+ fatal_error_dump_runtime (FILE * stream , _PyRuntimeState * runtime )
2074+ {
2075+ fprintf (stream , "Python runtime state: " );
2076+ if (runtime -> finalizing ) {
2077+ fprintf (stream , "finalizing (tstate=%p)" , runtime -> finalizing );
2078+ }
2079+ else if (runtime -> initialized ) {
2080+ fprintf (stream , "initialized" );
2081+ }
2082+ else if (runtime -> core_initialized ) {
2083+ fprintf (stream , "core initialized" );
2084+ }
2085+ else if (runtime -> preinitialized ) {
2086+ fprintf (stream , "preinitialized" );
2087+ }
2088+ else if (runtime -> preinitializing ) {
2089+ fprintf (stream , "preinitializing" );
2090+ }
2091+ else {
2092+ fprintf (stream , "unknown" );
2093+ }
2094+ fprintf (stream , "\n" );
2095+ fflush (stream );
2096+ }
2097+
2098+
20652099static void _Py_NO_RETURN
20662100fatal_error (const char * prefix , const char * msg , int status )
20672101{
2068- const int fd = fileno (stderr );
2102+ FILE * stream = stderr ;
2103+ const int fd = fileno (stream );
20692104 static int reentrant = 0 ;
20702105
20712106 if (reentrant ) {
@@ -2075,45 +2110,48 @@ fatal_error(const char *prefix, const char *msg, int status)
20752110 }
20762111 reentrant = 1 ;
20772112
2078- fprintf (stderr , "Fatal Python error: " );
2113+ fprintf (stream , "Fatal Python error: " );
20792114 if (prefix ) {
2080- fputs (prefix , stderr );
2081- fputs (": " , stderr );
2115+ fputs (prefix , stream );
2116+ fputs (": " , stream );
20822117 }
20832118 if (msg ) {
2084- fputs (msg , stderr );
2119+ fputs (msg , stream );
20852120 }
20862121 else {
2087- fprintf (stderr , "<message not set>" );
2122+ fprintf (stream , "<message not set>" );
20882123 }
2089- fputs ("\n" , stderr );
2090- fflush (stderr ); /* it helps in Windows debug build */
2124+ fputs ("\n" , stream );
2125+ fflush (stream ); /* it helps in Windows debug build */
20912126
2092- /* Check if the current thread has a Python thread state
2093- and holds the GIL */
2094- PyThreadState * tss_tstate = PyGILState_GetThisThreadState ();
2095- if (tss_tstate != NULL ) {
2096- PyThreadState * tstate = _PyThreadState_GET ();
2097- if (tss_tstate != tstate ) {
2098- /* The Python thread does not hold the GIL */
2099- tss_tstate = NULL ;
2100- }
2101- }
2102- else {
2103- /* Py_FatalError() has been called from a C thread
2104- which has no Python thread state. */
2127+ _PyRuntimeState * runtime = & _PyRuntime ;
2128+ fatal_error_dump_runtime (stream , runtime );
2129+
2130+ PyThreadState * tstate = _PyRuntimeState_GetThreadState (runtime );
2131+ PyInterpreterState * interp = NULL ;
2132+ if (tstate != NULL ) {
2133+ interp = tstate -> interp ;
21052134 }
2106- int has_tstate_and_gil = (tss_tstate != NULL );
21072135
2136+ /* Check if the current thread has a Python thread state
2137+ and holds the GIL.
2138+
2139+ tss_tstate is NULL if Py_FatalError() is called from a C thread which
2140+ has no Python thread state.
2141+
2142+ tss_tstate != tstate if the current Python thread does not hold the GIL.
2143+ */
2144+ PyThreadState * tss_tstate = PyGILState_GetThisThreadState ();
2145+ int has_tstate_and_gil = (tss_tstate != NULL && tss_tstate == tstate );
21082146 if (has_tstate_and_gil ) {
21092147 /* If an exception is set, print the exception with its traceback */
21102148 if (!_Py_FatalError_PrintExc (fd )) {
21112149 /* No exception is set, or an exception is set without traceback */
2112- _Py_FatalError_DumpTracebacks (fd );
2150+ _Py_FatalError_DumpTracebacks (fd , interp , tss_tstate );
21132151 }
21142152 }
21152153 else {
2116- _Py_FatalError_DumpTracebacks (fd );
2154+ _Py_FatalError_DumpTracebacks (fd , interp , tss_tstate );
21172155 }
21182156
21192157 /* The main purpose of faulthandler is to display the traceback.
0 commit comments