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:
Antoine Pitrou 2013-05-05 23:47:09 +02:00
parent 39b17c513a
commit 8408cea0cd
5 changed files with 88 additions and 8 deletions

View file

@ -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)
{