From 236becac6f43db20a332ad014f613a2dfa4151c6 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 21 May 2021 17:08:30 +0100 Subject: [PATCH 1/2] Defer clearing last thread state until last GC has been run. --- Python/pystate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Python/pystate.c b/Python/pystate.c index 36057ee13bded9..d1b5aa5d43fad8 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -292,7 +292,9 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) HEAD_LOCK(runtime); for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { - PyThreadState_Clear(p); + if (p != tstate) { + PyThreadState_Clear(p); + } } HEAD_UNLOCK(runtime); @@ -324,6 +326,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) /* Last garbage collection on this interpreter */ _PyGC_CollectNoFail(tstate); + PyThreadState_Clear(tstate); _PyGC_Fini(interp); /* We don't clear sysdict and builtins until the end of this function. From ddad17e11ea6aa42d4a26e2ee173532bc9368cd7 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Sat, 22 May 2021 11:52:13 +0100 Subject: [PATCH 2/2] Delay deletion of stack chunks until thread state is deleted. --- Python/pystate.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c index d1b5aa5d43fad8..64dcd577a0ffdb 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -292,9 +292,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) HEAD_LOCK(runtime); for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { - if (p != tstate) { - PyThreadState_Clear(p); - } + PyThreadState_Clear(p); } HEAD_UNLOCK(runtime); @@ -326,7 +324,6 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) /* Last garbage collection on this interpreter */ _PyGC_CollectNoFail(tstate); - PyThreadState_Clear(tstate); _PyGC_Fini(interp); /* We don't clear sysdict and builtins until the end of this function. @@ -900,13 +897,6 @@ PyThreadState_Clear(PyThreadState *tstate) if (tstate->on_delete != NULL) { tstate->on_delete(tstate->on_delete_data); } - _PyStackChunk *chunk = tstate->datastack_chunk; - tstate->datastack_chunk = NULL; - while (chunk != NULL) { - _PyStackChunk *prev = chunk->previous; - _PyObject_VirtualFree(chunk, chunk->size); - chunk = prev; - } } @@ -939,6 +929,13 @@ tstate_delete_common(PyThreadState *tstate, { PyThread_tss_set(&gilstate->autoTSSkey, NULL); } + _PyStackChunk *chunk = tstate->datastack_chunk; + tstate->datastack_chunk = NULL; + while (chunk != NULL) { + _PyStackChunk *prev = chunk->previous; + _PyObject_VirtualFree(chunk, chunk->size); + chunk = prev; + } } static void