mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue #17094: Clear stale thread states after fork().
Note that this is a potentially disruptive change since it may release some system resources which would otherwise remain perpetually alive (e.g. database connections kept in thread-local storage).
This commit is contained in:
parent
39b17c513a
commit
8408cea0cd
5 changed files with 88 additions and 8 deletions
|
@ -414,6 +414,53 @@ PyThreadState_DeleteCurrent()
|
|||
#endif /* WITH_THREAD */
|
||||
|
||||
|
||||
/*
|
||||
* Delete all thread states except the one passed as argument.
|
||||
* Note that, if there is a current thread state, it *must* be the one
|
||||
* passed as argument. Also, this won't touch any other interpreters
|
||||
* than the current one, since we don't know which thread state should
|
||||
* be kept in those other interpreteres.
|
||||
*/
|
||||
void
|
||||
_PyThreadState_DeleteExcept(PyThreadState *tstate)
|
||||
{
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
PyThreadState *p, *next, *garbage;
|
||||
HEAD_LOCK();
|
||||
/* Remove all thread states, except tstate, from the linked list of
|
||||
thread states. This will allow calling PyThreadState_Clear()
|
||||
without holding the lock.
|
||||
XXX This would be simpler with a doubly-linked list. */
|
||||
garbage = interp->tstate_head;
|
||||
interp->tstate_head = tstate;
|
||||
if (garbage == tstate) {
|
||||
garbage = garbage->next;
|
||||
tstate->next = NULL;
|
||||
}
|
||||
else {
|
||||
for (p = garbage; p; p = p->next) {
|
||||
if (p->next == tstate) {
|
||||
p->next = tstate->next;
|
||||
tstate->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tstate->next != NULL)
|
||||
Py_FatalError("_PyThreadState_DeleteExcept: tstate not found "
|
||||
"in interpreter thread states");
|
||||
HEAD_UNLOCK();
|
||||
/* 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) {
|
||||
next = p->next;
|
||||
PyThreadState_Clear(p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyThreadState *
|
||||
PyThreadState_Get(void)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue