diff options
author | Jesse Noller <jnoller@gmail.com> | 2008-07-16 20:03:47 (GMT) |
---|---|---|
committer | Jesse Noller <jnoller@gmail.com> | 2008-07-16 20:03:47 (GMT) |
commit | 5e62ca4fea04ad7b349330c50dc11937ab3278f4 (patch) | |
tree | 3a37b08db904d9e9239b7d08f630f24c46569a61 /Lib/threading.py | |
parent | 1bbf4ea553a5089ec82377dd24531dd79e3357c6 (diff) | |
download | cpython-5e62ca4fea04ad7b349330c50dc11937ab3278f4.zip cpython-5e62ca4fea04ad7b349330c50dc11937ab3278f4.tar.gz cpython-5e62ca4fea04ad7b349330c50dc11937ab3278f4.tar.bz2 |
Apply patch for 874900: threading module can deadlock after fork
Diffstat (limited to 'Lib/threading.py')
-rw-r--r-- | Lib/threading.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/Lib/threading.py b/Lib/threading.py index bfca44c..8a1de42 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -825,6 +825,37 @@ except ImportError: from _threading_local import local +def _after_fork(): + # This function is called by Python/ceval.c:PyEval_ReInitThreads which + # is called from PyOS_AfterFork. Here we cleanup threading module state + # that should not exist after a fork. + + # Reset _active_limbo_lock, in case we forked while the lock was held + # by another (non-forked) thread. http://bugs.python.org/issue874900 + global _active_limbo_lock + _active_limbo_lock = _allocate_lock() + + # fork() only copied the current thread; clear references to others. + new_active = {} + current = current_thread() + with _active_limbo_lock: + for ident, thread in _active.iteritems(): + if thread is current: + # There is only one active thread. + new_active[ident] = thread + else: + # All the others are already stopped. + # We don't call _Thread__stop() because it tries to acquire + # thread._Thread__block which could also have been held while + # we forked. + thread._Thread__stopped = True + + _limbo.clear() + _active.clear() + _active.update(new_active) + assert len(_active) == 1 + + # Self-test code def _test(): |