Skip to content

Commit 192c547

Browse files
bpo-26558: Fix Py_FatalError() with GIL released (GH-10267)
Don't call _Py_FatalError_PrintExc() nor flush_std_files() if the current thread doesn't hold the GIL, or if the current thread has no Python state thread. (cherry picked from commit 3a228ab) Co-authored-by: Victor Stinner <vstinner@redhat.com>
1 parent 71b6c1a commit 192c547

1 file changed

Lines changed: 25 additions & 10 deletions

File tree

Python/pylifecycle.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,12 +2015,6 @@ _Py_FatalError_PrintExc(int fd)
20152015
PyObject *exception, *v, *tb;
20162016
int has_tb;
20172017

2018-
if (PyThreadState_GET() == NULL) {
2019-
/* The GIL is released: trying to acquire it is likely to deadlock,
2020-
just give up. */
2021-
return 0;
2022-
}
2023-
20242018
PyErr_Fetch(&exception, &v, &tb);
20252019
if (exception == NULL) {
20262020
/* No current exception */
@@ -2125,9 +2119,30 @@ fatal_error(const char *prefix, const char *msg, int status)
21252119
fputs("\n", stderr);
21262120
fflush(stderr); /* it helps in Windows debug build */
21272121

2128-
/* Print the exception (if an exception is set) with its traceback,
2129-
* or display the current Python stack. */
2130-
if (!_Py_FatalError_PrintExc(fd)) {
2122+
/* Check if the current thread has a Python thread state
2123+
and holds the GIL */
2124+
PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
2125+
if (tss_tstate != NULL) {
2126+
PyThreadState *tstate = PyThreadState_GET();
2127+
if (tss_tstate != tstate) {
2128+
/* The Python thread does not hold the GIL */
2129+
tss_tstate = NULL;
2130+
}
2131+
}
2132+
else {
2133+
/* Py_FatalError() has been called from a C thread
2134+
which has no Python thread state. */
2135+
}
2136+
int has_tstate_and_gil = (tss_tstate != NULL);
2137+
2138+
if (has_tstate_and_gil) {
2139+
/* If an exception is set, print the exception with its traceback */
2140+
if (!_Py_FatalError_PrintExc(fd)) {
2141+
/* No exception is set, or an exception is set without traceback */
2142+
_Py_FatalError_DumpTracebacks(fd);
2143+
}
2144+
}
2145+
else {
21312146
_Py_FatalError_DumpTracebacks(fd);
21322147
}
21332148

@@ -2138,7 +2153,7 @@ fatal_error(const char *prefix, const char *msg, int status)
21382153
_PyFaulthandler_Fini();
21392154

21402155
/* Check if the current Python thread hold the GIL */
2141-
if (PyThreadState_GET() != NULL) {
2156+
if (has_tstate_and_gil) {
21422157
/* Flush sys.stdout and sys.stderr */
21432158
flush_std_files();
21442159
}

0 commit comments

Comments
 (0)