From 9ad58acbe8b90b4d0f2d2e139e38bb5aa32b7fb6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Mar 2020 23:37:49 +0100 Subject: bpo-19466: Py_Finalize() clears daemon threads earlier (GH-18848) Clear the frames of daemon threads earlier during the Python shutdown to call objects destructors. So "unclosed file" resource warnings are now emitted for daemon threads in a more reliable way. Cleanup _PyThreadState_DeleteExcept() code: rename "garbage" to "list". --- Python/pystate.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index a1eb5239f7..f907fc1fc9 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -895,25 +895,30 @@ void _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) { PyInterpreterState *interp = tstate->interp; - PyThreadState *p, *next, *garbage; + HEAD_LOCK(runtime); /* Remove all thread states, except tstate, from the linked list of thread states. This will allow calling PyThreadState_Clear() without holding the lock. */ - garbage = interp->tstate_head; - if (garbage == tstate) - garbage = tstate->next; - if (tstate->prev) + PyThreadState *list = interp->tstate_head; + if (list == tstate) { + list = tstate->next; + } + if (tstate->prev) { tstate->prev->next = tstate->next; - if (tstate->next) + } + if (tstate->next) { tstate->next->prev = tstate->prev; + } tstate->prev = tstate->next = NULL; interp->tstate_head = tstate; HEAD_UNLOCK(runtime); + /* Clear and deallocate all stale thread states. Even if this executes Python code, we should be safe since it executes in the current thread, not one of the stale threads. */ - for (p = garbage; p; p = next) { + PyThreadState *p, *next; + for (p = list; p; p = next) { next = p->next; PyThreadState_Clear(p); PyMem_RawFree(p); -- cgit v1.2.1