]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39877: take_gil() checks tstate_must_exit() twice (GH-18890)
authorVictor Stinner <vstinner@python.org>
Mon, 9 Mar 2020 22:10:53 +0000 (23:10 +0100)
committerGitHub <noreply@github.com>
Mon, 9 Mar 2020 22:10:53 +0000 (23:10 +0100)
take_gil() now also checks tstate_must_exit() after acquiring
the GIL: exit the thread if Py_Finalize() has been called.

Python/ceval_gil.h

index 03f04b93e0a3295fe5ad0ee33ece25ea94062462..9c051ae57b03bcdf813036b83edeb13ba5f9e7eb 100644 (file)
@@ -213,8 +213,13 @@ take_gil(PyThreadState *tstate)
 
     assert(tstate != NULL);
 
-    /* Check if we should make a quick exit. */
     if (tstate_must_exit(tstate)) {
+        /* bpo-39877: If Py_Finalize() has been called and tstate is not the
+           thread which called Py_Finalize(), exit immediately the thread.
+
+           This code path can be reached by a daemon thread after Py_Finalize()
+           completes. In this case, tstate is a dangling pointer: points to
+           PyThreadState freed memory. */
         PyThread_exit_thread();
     }
 
@@ -282,6 +287,18 @@ _ready:
 
     MUTEX_UNLOCK(gil->mutex);
 
+    if (tstate_must_exit(tstate)) {
+        /* bpo-36475: If Py_Finalize() has been called and tstate is not
+           the thread which called Py_Finalize(), exit immediately the
+           thread.
+
+           This code path can be reached by a daemon thread which was waiting
+           in take_gil() while the main thread called
+           wait_for_thread_shutdown() from Py_Finalize(). */
+        drop_gil(ceval, tstate);
+        PyThread_exit_thread();
+    }
+
     errno = err;
 }