summaryrefslogtreecommitdiff
path: root/Lib/threading.py
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2008-08-17 23:01:11 +0000
committerGregory P. Smith <greg@mad-scientist.com>2008-08-17 23:01:11 +0000
commit5e8dc97a098766a566b07df241c524fbd56d34ac (patch)
tree2d9d31372c73d994c7cc2938177b70a272cf8580 /Lib/threading.py
parent1d63a45d0d25acec0174bb291e6cd4c7c0d7c00d (diff)
downloadcpython-git-5e8dc97a098766a566b07df241c524fbd56d34ac.tar.gz
Backport of r65032 from trunk
Fixes Issue #874900: after an os.fork() call the threading module state is cleaned up in the child process to prevent deadlock and report proper thread counts if the new process uses the threading module.
Diffstat (limited to 'Lib/threading.py')
-rw-r--r--Lib/threading.py34
1 files changed, 34 insertions, 0 deletions
diff --git a/Lib/threading.py b/Lib/threading.py
index bab3b42641..1ecc06eb33 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -766,6 +766,40 @@ 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 = currentThread()
+ _active_limbo_lock.acquire()
+ try:
+ 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
+ finally:
+ _active_limbo_lock.release()
+
+
# Self-test code
def _test():