Skip to content

Commit 9da7430

Browse files
authored
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().
1 parent d51a363 commit 9da7430

File tree

3 files changed

+35
-28
lines changed

3 files changed

+35
-28
lines changed

Modules/_xxsubinterpretersmodule.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2056,7 +2056,6 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
20562056
}
20572057

20582058
// Destroy the interpreter.
2059-
//PyInterpreterState_Delete(interp);
20602059
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
20612060
// XXX Possible GILState issues?
20622061
PyThreadState *save_tstate = PyThreadState_Swap(tstate);

Python/pylifecycle.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,9 +1226,6 @@ finalize_interp_delete(PyThreadState *tstate, int is_main_interp)
12261226
_PyGILState_Fini(tstate);
12271227
}
12281228

1229-
/* Delete current thread. After this, many C API calls become crashy. */
1230-
PyThreadState_Swap(NULL);
1231-
12321229
PyInterpreterState_Delete(tstate->interp);
12331230
}
12341231

@@ -1577,9 +1574,9 @@ new_interpreter(PyThreadState **tstate_p)
15771574

15781575
PyErr_PrintEx(0);
15791576
PyThreadState_Clear(tstate);
1580-
PyThreadState_Swap(save_tstate);
15811577
PyThreadState_Delete(tstate);
15821578
PyInterpreterState_Delete(interp);
1579+
PyThreadState_Swap(save_tstate);
15831580

15841581
*tstate_p = NULL;
15851582
return _PyStatus_OK();

Python/pystate.c

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939

4040
/* Forward declarations */
4141
static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate);
42+
static void _PyThreadState_Delete(PyThreadState *tstate, int check_current);
4243

4344

4445
static PyStatus
@@ -295,13 +296,13 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
295296

296297

297298
static void
298-
zapthreads(PyInterpreterState *interp)
299+
zapthreads(PyInterpreterState *interp, int check_current)
299300
{
300-
PyThreadState *p;
301+
PyThreadState *tstate;
301302
/* No need to lock the mutex here because this should only happen
302303
when the threads are all really dead (XXX famous last words). */
303-
while ((p = interp->tstate_head) != NULL) {
304-
PyThreadState_Delete(p);
304+
while ((tstate = interp->tstate_head) != NULL) {
305+
_PyThreadState_Delete(tstate, check_current);
305306
}
306307
}
307308

@@ -311,7 +312,11 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
311312
{
312313
_PyRuntimeState *runtime = interp->runtime;
313314
struct pyinterpreters *interpreters = &runtime->interpreters;
314-
zapthreads(interp);
315+
zapthreads(interp, 0);
316+
317+
/* Delete current thread. After this, many C API calls become crashy. */
318+
_PyThreadState_Swap(&runtime->gilstate, NULL);
319+
315320
HEAD_LOCK(runtime);
316321
PyInterpreterState **p;
317322
for (p = &interpreters->head; ; p = &(*p)->next) {
@@ -367,7 +372,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
367372
}
368373

369374
PyInterpreterState_Clear(interp); // XXX must activate?
370-
zapthreads(interp);
375+
zapthreads(interp, 1);
371376
if (interp->id_mutex != NULL) {
372377
PyThread_free_lock(interp->id_mutex);
373378
}
@@ -793,7 +798,8 @@ PyThreadState_Clear(PyThreadState *tstate)
793798

794799
/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
795800
static void
796-
tstate_delete_common(PyThreadState *tstate)
801+
tstate_delete_common(PyThreadState *tstate,
802+
struct _gilstate_runtime_state *gilstate)
797803
{
798804
_PyRuntimeState *runtime = tstate->interp->runtime;
799805
if (tstate == NULL) {
@@ -815,22 +821,32 @@ tstate_delete_common(PyThreadState *tstate)
815821
tstate->on_delete(tstate->on_delete_data);
816822
}
817823
PyMem_RawFree(tstate);
818-
}
819-
820824

821-
void
822-
PyThreadState_Delete(PyThreadState *tstate)
823-
{
824-
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
825-
if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
826-
Py_FatalError("PyThreadState_Delete: tstate is still current");
827-
}
828825
if (gilstate->autoInterpreterState &&
829826
PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
830827
{
831828
PyThread_tss_set(&gilstate->autoTSSkey, NULL);
832829
}
833-
tstate_delete_common(tstate);
830+
}
831+
832+
833+
static void
834+
_PyThreadState_Delete(PyThreadState *tstate, int check_current)
835+
{
836+
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
837+
if (check_current) {
838+
if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
839+
Py_FatalError("PyThreadState_Delete: tstate is still current");
840+
}
841+
}
842+
tstate_delete_common(tstate, gilstate);
843+
}
844+
845+
846+
void
847+
PyThreadState_Delete(PyThreadState *tstate)
848+
{
849+
_PyThreadState_Delete(tstate, 1);
834850
}
835851

836852

@@ -842,12 +858,7 @@ _PyThreadState_DeleteCurrent(_PyRuntimeState *runtime)
842858
if (tstate == NULL)
843859
Py_FatalError(
844860
"PyThreadState_DeleteCurrent: no current tstate");
845-
tstate_delete_common(tstate);
846-
if (gilstate->autoInterpreterState &&
847-
PyThread_tss_get(&gilstate->autoTSSkey) == tstate)
848-
{
849-
PyThread_tss_set(&gilstate->autoTSSkey, NULL);
850-
}
861+
tstate_delete_common(tstate, gilstate);
851862
_PyRuntimeGILState_SetThreadState(gilstate, NULL);
852863
PyEval_ReleaseLock();
853864
}

0 commit comments

Comments
 (0)