]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-36854: Clear the current thread later (GH-17279)
authorVictor Stinner <vstinner@python.org>
Wed, 20 Nov 2019 10:17:17 +0000 (11:17 +0100)
committerGitHub <noreply@github.com>
Wed, 20 Nov 2019 10:17:17 +0000 (11:17 +0100)
Clear the current thread later in the Python finalization.

* The PyInterpreterState_Delete() function is now responsible
  to call PyThreadState_Swap(NULL).
* The tstate_delete_common() function is now responsible to clear the
  "autoTSSKey" thread local storage and it only clears it once the
  thread state is fully cleared. It allows to still get the current
  thread from TSS in tstate_delete_common().

Modules/_xxsubinterpretersmodule.c
Python/pylifecycle.c
Python/pystate.c

index 7842947e54ac56c35245162953cf8c3e41b3acb5..4a6ffdd3266783a7359d90eac8d5f81c63f4e7f2 100644 (file)
@@ -2056,7 +2056,6 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
     }
 
     // Destroy the interpreter.
-    //PyInterpreterState_Delete(interp);
     PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
     // XXX Possible GILState issues?
     PyThreadState *save_tstate = PyThreadState_Swap(tstate);
index 2975b3ebd6651dd4565791f45f38dee21c985649..73114df79cd8e33047094c5ce5c232e5bf5b940f 100644 (file)
@@ -1226,9 +1226,6 @@ finalize_interp_delete(PyThreadState *tstate, int is_main_interp)
         _PyGILState_Fini(tstate);
     }
 
-    /* Delete current thread. After this, many C API calls become crashy. */
-    PyThreadState_Swap(NULL);
-
     PyInterpreterState_Delete(tstate->interp);
 }
 
@@ -1577,9 +1574,9 @@ handle_error:
 
     PyErr_PrintEx(0);
     PyThreadState_Clear(tstate);
-    PyThreadState_Swap(save_tstate);
     PyThreadState_Delete(tstate);
     PyInterpreterState_Delete(interp);
+    PyThreadState_Swap(save_tstate);
 
     *tstate_p = NULL;
     return _PyStatus_OK();
index 8fff161dac0f50dd7de136ab553ea9235138aa90..93f0ce798888dc4e7c78d822928b03b9234bec25 100644 (file)
@@ -39,6 +39,7 @@ extern "C" {
 
 /* Forward declarations */
 static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate);
+static void _PyThreadState_Delete(PyThreadState *tstate, int check_current);
 
 
 static PyStatus
@@ -295,13 +296,13 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
 
 
 static void
-zapthreads(PyInterpreterState *interp)
+zapthreads(PyInterpreterState *interp, int check_current)
 {
-    PyThreadState *p;
+    PyThreadState *tstate;
     /* No need to lock the mutex here because this should only happen
        when the threads are all really dead (XXX famous last words). */
-    while ((p = interp->tstate_head) != NULL) {
-        PyThreadState_Delete(p);
+    while ((tstate = interp->tstate_head) != NULL) {
+        _PyThreadState_Delete(tstate, check_current);
     }
 }
 
@@ -311,7 +312,11 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
 {
     _PyRuntimeState *runtime = interp->runtime;
     struct pyinterpreters *interpreters = &runtime->interpreters;
-    zapthreads(interp);
+    zapthreads(interp, 0);
+
+    /* Delete current thread. After this, many C API calls become crashy. */
+    _PyThreadState_Swap(&runtime->gilstate, NULL);
+
     HEAD_LOCK(runtime);
     PyInterpreterState **p;
     for (p = &interpreters->head; ; p = &(*p)->next) {
@@ -367,7 +372,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
         }
 
         PyInterpreterState_Clear(interp);  // XXX must activate?
-        zapthreads(interp);
+        zapthreads(interp, 1);
         if (interp->id_mutex != NULL) {
             PyThread_free_lock(interp->id_mutex);
         }
@@ -793,7 +798,8 @@ PyThreadState_Clear(PyThreadState *tstate)
 
 /* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
 static void
-tstate_delete_common(PyThreadState *tstate)
+tstate_delete_common(PyThreadState *tstate,
+                     struct _gilstate_runtime_state *gilstate)
 {
     _PyRuntimeState *runtime = tstate->interp->runtime;
     if (tstate == NULL) {
@@ -815,22 +821,32 @@ tstate_delete_common(PyThreadState *tstate)
         tstate->on_delete(tstate->on_delete_data);
     }
     PyMem_RawFree(tstate);
-}
-
 
-void
-PyThreadState_Delete(PyThreadState *tstate)
-{
-    struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
-    if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
-        Py_FatalError("PyThreadState_Delete: tstate is still current");
-    }
     if (gilstate->autoInterpreterState &&
         PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
     {
         PyThread_tss_set(&gilstate->autoTSSkey, NULL);
     }
-    tstate_delete_common(tstate);
+}
+
+
+static void
+_PyThreadState_Delete(PyThreadState *tstate, int check_current)
+{
+    struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
+    if (check_current) {
+        if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
+            Py_FatalError("PyThreadState_Delete: tstate is still current");
+        }
+    }
+    tstate_delete_common(tstate, gilstate);
+}
+
+
+void
+PyThreadState_Delete(PyThreadState *tstate)
+{
+    _PyThreadState_Delete(tstate, 1);
 }
 
 
@@ -842,12 +858,7 @@ _PyThreadState_DeleteCurrent(_PyRuntimeState *runtime)
     if (tstate == NULL)
         Py_FatalError(
             "PyThreadState_DeleteCurrent: no current tstate");
-    tstate_delete_common(tstate);
-    if (gilstate->autoInterpreterState &&
-        PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
-    {
-        PyThread_tss_set(&gilstate->autoTSSkey, NULL);
-    }
+    tstate_delete_common(tstate, gilstate);
     _PyRuntimeGILState_SetThreadState(gilstate, NULL);
     PyEval_ReleaseLock();
 }