Skip to content

Commit 3a228ab

Browse files
authored
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.
1 parent 2be00d9 commit 3a228ab

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

Python/pylifecycle.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,12 +1820,6 @@ _Py_FatalError_PrintExc(int fd)
18201820
PyObject *exception, *v, *tb;
18211821
int has_tb;
18221822

1823-
if (PyThreadState_GET() == NULL) {
1824-
/* The GIL is released: trying to acquire it is likely to deadlock,
1825-
just give up. */
1826-
return 0;
1827-
}
1828-
18291823
PyErr_Fetch(&exception, &v, &tb);
18301824
if (exception == NULL) {
18311825
/* No current exception */
@@ -1930,9 +1924,30 @@ fatal_error(const char *prefix, const char *msg, int status)
19301924
fputs("\n", stderr);
19311925
fflush(stderr); /* it helps in Windows debug build */
19321926

1933-
/* Print the exception (if an exception is set) with its traceback,
1934-
* or display the current Python stack. */
1935-
if (!_Py_FatalError_PrintExc(fd)) {
1927+
/* Check if the current thread has a Python thread state
1928+
and holds the GIL */
1929+
PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
1930+
if (tss_tstate != NULL) {
1931+
PyThreadState *tstate = PyThreadState_GET();
1932+
if (tss_tstate != tstate) {
1933+
/* The Python thread does not hold the GIL */
1934+
tss_tstate = NULL;
1935+
}
1936+
}
1937+
else {
1938+
/* Py_FatalError() has been called from a C thread
1939+
which has no Python thread state. */
1940+
}
1941+
int has_tstate_and_gil = (tss_tstate != NULL);
1942+
1943+
if (has_tstate_and_gil) {
1944+
/* If an exception is set, print the exception with its traceback */
1945+
if (!_Py_FatalError_PrintExc(fd)) {
1946+
/* No exception is set, or an exception is set without traceback */
1947+
_Py_FatalError_DumpTracebacks(fd);
1948+
}
1949+
}
1950+
else {
19361951
_Py_FatalError_DumpTracebacks(fd);
19371952
}
19381953

@@ -1943,7 +1958,7 @@ fatal_error(const char *prefix, const char *msg, int status)
19431958
_PyFaulthandler_Fini();
19441959

19451960
/* Check if the current Python thread hold the GIL */
1946-
if (PyThreadState_GET() != NULL) {
1961+
if (has_tstate_and_gil) {
19471962
/* Flush sys.stdout and sys.stderr */
19481963
flush_std_files();
19491964
}

0 commit comments

Comments
 (0)