diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2013-05-05 21:47:09 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2013-05-05 21:47:09 (GMT) |
commit | 8408cea0cdc0ccd5900acd99a9a51dd9161ae319 (patch) | |
tree | 0dcb39ac0cf5fc5e293941763a31bd2472dd004b /Python/pystate.c | |
parent | 39b17c513ae7b9baecdc8292876683647186fee4 (diff) | |
download | cpython-8408cea0cdc0ccd5900acd99a9a51dd9161ae319.zip cpython-8408cea0cdc0ccd5900acd99a9a51dd9161ae319.tar.gz cpython-8408cea0cdc0ccd5900acd99a9a51dd9161ae319.tar.bz2 |
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).
Diffstat (limited to 'Python/pystate.c')
-rw-r--r-- | Python/pystate.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index 7003893..2a6f16c 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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) { |