[3.6] bpo-31310: multiprocessing's semaphore tracker should be launch… · python/cpython@b5f09ac

@@ -4,6 +4,7 @@

4455

import unittest

66

import queue as pyqueue

7+

import contextlib

78

import time

89

import io

910

import itertools

@@ -4125,14 +4126,14 @@ def test_preload_resources(self):

41254126

self.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")

41344131

class TestSemaphoreTracker(unittest.TestCase):

4132+41354133

def test_semaphore_tracker(self):

4134+

#

4135+

# Check that killing process does not leak named semaphores

4136+

#

41364137

import subprocess

41374138

cmd = '''if 1:

41384139

import multiprocessing as mp, time, os

@@ -4166,6 +4167,40 @@ def test_semaphore_tracker(self):

41664167

self.assertRegex(err, expected)

41674168

self.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+41694204

class TestSimpleQueue(unittest.TestCase):

4170420541714206

@classmethod