[3.6] bpo-31310: multiprocessing's semaphore tracker should be launch… · python/cpython@b5f09ac
@@ -4,6 +4,7 @@
4455import unittest
66import queue as pyqueue
7+import contextlib
78import time
89import io
910import itertools
@@ -4125,14 +4126,14 @@ def test_preload_resources(self):
41254126self.fail("failed spawning forkserver or grandchild")
41264127412741284128-#
4129-# Check that killing process does not leak named semaphores
4130-#
4131-41324129@unittest.skipIf(sys.platform == "win32",
41334130 "test semantics don't make sense on Windows")
41344131class TestSemaphoreTracker(unittest.TestCase):
4132+41354133def test_semaphore_tracker(self):
4134+#
4135+# Check that killing process does not leak named semaphores
4136+#
41364137import subprocess
41374138cmd = '''if 1:
41384139 import multiprocessing as mp, time, os
@@ -4166,6 +4167,40 @@ def test_semaphore_tracker(self):
41664167self.assertRegex(err, expected)
41674168self.assertRegex(err, r'semaphore_tracker: %r: \[Errno' % name1)
416841694170+def check_semaphore_tracker_death(self, signum, should_die):
4171+# bpo-31310: if the semaphore tracker process has died, it should
4172+# be restarted implicitly.
4173+from multiprocessing.semaphore_tracker import _semaphore_tracker
4174+_semaphore_tracker.ensure_running()
4175+pid = _semaphore_tracker._pid
4176+os.kill(pid, signum)
4177+time.sleep(1.0) # give it time to die
4178+4179+ctx = multiprocessing.get_context("spawn")
4180+with contextlib.ExitStack() as stack:
4181+if should_die:
4182+stack.enter_context(self.assertWarnsRegex(
4183+UserWarning,
4184+"semaphore_tracker: process died"))
4185+sem = ctx.Semaphore()
4186+sem.acquire()
4187+sem.release()
4188+wr = weakref.ref(sem)
4189+# ensure `sem` gets collected, which triggers communication with
4190+# the semaphore tracker
4191+del sem
4192+gc.collect()
4193+self.assertIsNone(wr())
4194+4195+def test_semaphore_tracker_sigint(self):
4196+# Catchable signal (ignored by semaphore tracker)
4197+self.check_semaphore_tracker_death(signal.SIGINT, False)
4198+4199+def test_semaphore_tracker_sigkill(self):
4200+# Uncatchable signal.
4201+self.check_semaphore_tracker_death(signal.SIGKILL, True)
4202+4203+41694204class TestSimpleQueue(unittest.TestCase):
4170420541714206@classmethod