bpo-38070: Py_FatalError() logs runtime state (GH-16246) · python/cpython@1ce16fb (original) (raw)

`@@ -1975,13 +1975,14 @@ init_sys_streams(PyThreadState *tstate)

`

1975

1975

``

1976

1976

``

1977

1977

`static void

`

1978

``

`-

_Py_FatalError_DumpTracebacks(int fd)

`

``

1978

`+

_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,

`

``

1979

`+

PyThreadState *tstate)

`

1979

1980

`{

`

1980

1981

`fputc('\n', stderr);

`

1981

1982

`fflush(stderr);

`

1982

1983

``

1983

1984

`/* display the current Python stack */

`

1984

``

`-

_Py_DumpTracebackThreads(fd, NULL, NULL);

`

``

1985

`+

_Py_DumpTracebackThreads(fd, interp, tstate);

`

1985

1986

`}

`

1986

1987

``

1987

1988

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

`

`@@ -2079,10 +2080,39 @@ fatal_output_debug(const char *msg)

`

2079

2080

`}

`

2080

2081

`#endif

`

2081

2082

``

``

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

+

2082

2111

`static void _Py_NO_RETURN

`

2083

2112

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

`

2084

2113

`{

`

2085

``

`-

const int fd = fileno(stderr);

`

``

2114

`+

FILE *stream = stderr;

`

``

2115

`+

const int fd = fileno(stream);

`

2086

2116

`static int reentrant = 0;

`

2087

2117

``

2088

2118

`if (reentrant) {

`

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

`

2092

2122

` }

`

2093

2123

`reentrant = 1;

`

2094

2124

``

2095

``

`-

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

`

``

2125

`+

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

`

2096

2126

`if (prefix) {

`

2097

``

`-

fputs(prefix, stderr);

`

2098

``

`-

fputs(": ", stderr);

`

``

2127

`+

fputs(prefix, stream);

`

``

2128

`+

fputs(": ", stream);

`

2099

2129

` }

`

2100

2130

`if (msg) {

`

2101

``

`-

fputs(msg, stderr);

`

``

2131

`+

fputs(msg, stream);

`

2102

2132

` }

`

2103

2133

`else {

`

2104

``

`-

fprintf(stderr, "");

`

``

2134

`+

fprintf(stream, "");

`

2105

2135

` }

`

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

`

2108

2138

``

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;

`

2122

2146

` }

`

2123

``

`-

int has_tstate_and_gil = (tss_tstate != NULL);

`

2124

2147

``

``

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

`

2125

2158

`if (has_tstate_and_gil) {

`

2126

2159

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

`

2127

2160

`if (!_Py_FatalError_PrintExc(fd)) {

`

2128

2161

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

`

2129

``

`-

_Py_FatalError_DumpTracebacks(fd);

`

``

2162

`+

_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);

`

2130

2163

` }

`

2131

2164

` }

`

2132

2165

`else {

`

2133

``

`-

_Py_FatalError_DumpTracebacks(fd);

`

``

2166

`+

_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);

`

2134

2167

` }

`

2135

2168

``

2136

2169

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

`