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().
This commit is contained in:
Victor Stinner 2019-11-20 11:17:17 +01:00 committed by GitHub
parent d51a363a43
commit 9da7430675
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 28 deletions

View 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);

View 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();

View 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);
if (gilstate->autoInterpreterState &&
PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
{
PyThread_tss_set(&gilstate->autoTSSkey, NULL);
}
}
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)
{
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);
_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();
}