diff options
author | Charles-François Natali <cf.natali@gmail.com> | 2013-08-30 21:34:26 (GMT) |
---|---|---|
committer | Charles-François Natali <cf.natali@gmail.com> | 2013-08-30 21:34:26 (GMT) |
commit | 79a53ea7d7d66f515b6bd4a38b1adbe8961a69f2 (patch) | |
tree | 1fad390e1918b6039c2cf2490d853614b52827ce /Lib | |
parent | b586934f0eb69a3c04e1756abe9aa5a4ab307518 (diff) | |
parent | 9939cc89a4ee54ab50719a597a8b8a0795a691f6 (diff) | |
download | cpython-79a53ea7d7d66f515b6bd4a38b1adbe8961a69f2.zip cpython-79a53ea7d7d66f515b6bd4a38b1adbe8961a69f2.tar.gz cpython-79a53ea7d7d66f515b6bd4a38b1adbe8961a69f2.tar.bz2 |
Issue #18418: After fork(), reinit all threads states, not only active ones.
Patch by A. Jesse Jiryu Davis.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_threading.py | 21 | ||||
-rw-r--r-- | Lib/threading.py | 2 |
2 files changed, 22 insertions, 1 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 3629749..0a78f8c 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -445,6 +445,27 @@ class ThreadTests(BaseTestCase): self.assertEqual(out, b'') self.assertEqual(err, b'') + @unittest.skipUnless(hasattr(os, 'fork'), "needs os.fork()") + def test_is_alive_after_fork(self): + # Try hard to trigger #18418: is_alive() could sometimes be True on + # threads that vanished after a fork. + old_interval = sys.getswitchinterval() + self.addCleanup(sys.setswitchinterval, old_interval) + + # Make the bug more likely to manifest. + sys.setswitchinterval(1e-6) + + for i in range(20): + t = threading.Thread(target=lambda: None) + t.start() + self.addCleanup(t.join) + pid = os.fork() + if pid == 0: + os._exit(1 if t.is_alive() else 0) + else: + pid, status = os.waitpid(pid, 0) + self.assertEqual(0, status) + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py index c7f919c..21bc781 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -940,7 +940,7 @@ def _after_fork(): new_active = {} current = current_thread() with _active_limbo_lock: - for thread in _active.values(): + for thread in _enumerate(): # Any lock/condition variable may be currently locked or in an # invalid state, so we reinitialize them. thread._reset_internal_locks() |