[3.8] bpo-38070: Py_FatalError() logs runtime state (GH-16258) · python/cpython@47bbab9 (original) (raw)

`@@ -719,11 +719,15 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)

`

719

719

` }

`

720

720

`_PyRuntimeState *runtime = &_PyRuntime;

`

721

721

``

722

``

`-

if (runtime->pre_initialized) {

`

``

722

`+

if (runtime->preinitialized) {

`

723

723

`/* If it's already configured: ignored the new configuration */

`

724

724

`return _PyStatus_OK();

`

725

725

` }

`

726

726

``

``

727

`+

/* Note: preinitialized remains 1 on error, it is only set to 0

`

``

728

`+

at exit on success. */

`

``

729

`+

runtime->preinitializing = 1;

`

``

730

+

727

731

`PyPreConfig config;

`

728

732

`_PyPreConfig_InitFromPreConfig(&config, src_config);

`

729

733

``

`@@ -737,7 +741,8 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)

`

737

741

`return status;

`

738

742

` }

`

739

743

``

740

``

`-

runtime->pre_initialized = 1;

`

``

744

`+

runtime->preinitializing = 0;

`

``

745

`+

runtime->preinitialized = 1;

`

741

746

`return _PyStatus_OK();

`

742

747

`}

`

743

748

``

`@@ -777,7 +782,7 @@ _Py_PreInitializeFromConfig(const PyConfig *config,

`

777

782

` }

`

778

783

`_PyRuntimeState *runtime = &_PyRuntime;

`

779

784

``

780

``

`-

if (runtime->pre_initialized) {

`

``

785

`+

if (runtime->preinitialized) {

`

781

786

`/* Already initialized: do nothing */

`

782

787

`return _PyStatus_OK();

`

783

788

` }

`

`@@ -1961,13 +1966,14 @@ init_sys_streams(PyInterpreterState *interp)

`

1961

1966

``

1962

1967

``

1963

1968

`static void

`

1964

``

`-

_Py_FatalError_DumpTracebacks(int fd)

`

``

1969

`+

_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,

`

``

1970

`+

PyThreadState *tstate)

`

1965

1971

`{

`

1966

1972

`fputc('\n', stderr);

`

1967

1973

`fflush(stderr);

`

1968

1974

``

1969

1975

`/* display the current Python stack */

`

1970

``

`-

_Py_DumpTracebackThreads(fd, NULL, NULL);

`

``

1976

`+

_Py_DumpTracebackThreads(fd, interp, tstate);

`

1971

1977

`}

`

1972

1978

``

1973

1979

`/* Print the current exception (if an exception is set) with its traceback,

`

`@@ -2062,10 +2068,39 @@ fatal_output_debug(const char *msg)

`

2062

2068

`}

`

2063

2069

`#endif

`

2064

2070

``

``

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

+

2065

2099

`static void _Py_NO_RETURN

`

2066

2100

`fatal_error(const char *prefix, const char *msg, int status)

`

2067

2101

`{

`

2068

``

`-

const int fd = fileno(stderr);

`

``

2102

`+

FILE *stream = stderr;

`

``

2103

`+

const int fd = fileno(stream);

`

2069

2104

`static int reentrant = 0;

`

2070

2105

``

2071

2106

`if (reentrant) {

`

`@@ -2075,45 +2110,48 @@ fatal_error(const char *prefix, const char *msg, int status)

`

2075

2110

` }

`

2076

2111

`reentrant = 1;

`

2077

2112

``

2078

``

`-

fprintf(stderr, "Fatal Python error: ");

`

``

2113

`+

fprintf(stream, "Fatal Python error: ");

`

2079

2114

`if (prefix) {

`

2080

``

`-

fputs(prefix, stderr);

`

2081

``

`-

fputs(": ", stderr);

`

``

2115

`+

fputs(prefix, stream);

`

``

2116

`+

fputs(": ", stream);

`

2082

2117

` }

`

2083

2118

`if (msg) {

`

2084

``

`-

fputs(msg, stderr);

`

``

2119

`+

fputs(msg, stream);

`

2085

2120

` }

`

2086

2121

`else {

`

2087

``

`-

fprintf(stderr, "");

`

``

2122

`+

fprintf(stream, "");

`

2088

2123

` }

`

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 */

`

2091

2126

``

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;

`

2105

2134

` }

`

2106

``

`-

int has_tstate_and_gil = (tss_tstate != NULL);

`

2107

2135

``

``

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);

`

2108

2146

`if (has_tstate_and_gil) {

`

2109

2147

`/* If an exception is set, print the exception with its traceback */

`

2110

2148

`if (!_Py_FatalError_PrintExc(fd)) {

`

2111

2149

`/* No exception is set, or an exception is set without traceback */

`

2112

``

`-

_Py_FatalError_DumpTracebacks(fd);

`

``

2150

`+

_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);

`

2113

2151

` }

`

2114

2152

` }

`

2115

2153

`else {

`

2116

``

`-

_Py_FatalError_DumpTracebacks(fd);

`

``

2154

`+

_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);

`

2117

2155

` }

`

2118

2156

``

2119

2157

`/* The main purpose of faulthandler is to display the traceback.

`