[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.
`