summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2019-11-20 10:17:17 (GMT)
committerGitHub <noreply@github.com>2019-11-20 10:17:17 (GMT)
commit9da7430675ceaeae5abeb9c9f7cd552b71b3a93a (patch)
treef78a3703f3d8ca26714e1f20cc08df9102f60eab
parentd51a363a4379385fdfe9c09a56324631465ede29 (diff)
downloadcpython-9da7430675ceaeae5abeb9c9f7cd552b71b3a93a.zip
cpython-9da7430675ceaeae5abeb9c9f7cd552b71b3a93a.tar.gz
cpython-9da7430675ceaeae5abeb9c9f7cd552b71b3a93a.tar.bz2
bpo-36854: Clear the current thread later (GH-17279)
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().
-rw-r--r--Modules/_xxsubinterpretersmodule.c1
-rw-r--r--Python/pylifecycle.c5
-rw-r--r--Python/pystate.c57
3 files changed, 35 insertions, 28 deletions
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c
index 7842947..4a6ffdd 100644
--- a/Modules/_xxsubinterpretersmodule.c
+++ b/Modules/_xxsubinterpretersmodule.c
@@ -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);
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 2975b3e..73114df 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -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();
diff --git a/Python/pystate.c b/Python/pystate.c
index 8fff161..93f0ce7 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -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();
}