[Python-checkins] bpo-26558: Fix Py_FatalError() with GIL released (GH-10267) (GH-10270)

Victor Stinner webhook-mailer at python.org
Wed Oct 31 20:11:58 EDT 2018


https://github.com/python/cpython/commit/ff56597151206a03ce421712516323430b7749c8
commit: ff56597151206a03ce421712516323430b7749c8
branch: 3.6
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-11-01T01:11:54+01:00
summary:

bpo-26558: Fix Py_FatalError() with GIL released (GH-10267) (GH-10270)

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 3a228ab17c2a9cffd1a2f15f30d6209768de20a6)

files:
M Python/pylifecycle.c

diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index ecfdfee218dc..56f04afc7701 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1356,12 +1356,6 @@ _Py_FatalError_PrintExc(int fd)
     PyObject *exception, *v, *tb;
     int has_tb;
 
-    if (PyThreadState_GET() == NULL) {
-        /* The GIL is released: trying to acquire it is likely to deadlock,
-           just give up. */
-        return 0;
-    }
-
     PyErr_Fetch(&exception, &v, &tb);
     if (exception == NULL) {
         /* No current exception */
@@ -1425,10 +1419,32 @@ Py_FatalError(const char *msg)
     fprintf(stderr, "Fatal Python error: %s\n", msg);
     fflush(stderr); /* it helps in Windows debug build */
 
-    /* Print the exception (if an exception is set) with its traceback,
-     * or display the current Python stack. */
-    if (!_Py_FatalError_PrintExc(fd))
+    /* Check if the current thread has a Python thread state
+       and holds the GIL */
+    PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
+    if (tss_tstate != NULL) {
+        PyThreadState *tstate = PyThreadState_GET();
+        if (tss_tstate != tstate) {
+            /* The Python thread does not hold the GIL */
+            tss_tstate = NULL;
+        }
+    }
+    else {
+        /* Py_FatalError() has been called from a C thread
+           which has no Python thread state. */
+    }
+    int has_tstate_and_gil = (tss_tstate != NULL);
+
+    if (has_tstate_and_gil) {
+        /* If an exception is set, print the exception with its traceback */
+        if (!_Py_FatalError_PrintExc(fd)) {
+            /* No exception is set, or an exception is set without traceback */
+            _Py_FatalError_DumpTracebacks(fd);
+        }
+    }
+    else {
         _Py_FatalError_DumpTracebacks(fd);
+    }
 
     /* The main purpose of faulthandler is to display the traceback. We already
      * did our best to display it. So faulthandler can now be disabled.
@@ -1436,7 +1452,7 @@ Py_FatalError(const char *msg)
     _PyFaulthandler_Fini();
 
     /* Check if the current Python thread hold the GIL */
-    if (PyThreadState_GET() != NULL) {
+    if (has_tstate_and_gil) {
         /* Flush sys.stdout and sys.stderr */
         flush_std_files();
     }



More information about the Python-checkins mailing list