Skip to content

Commit 4f9babb

Browse files
committed
Implement PONG command in the semaphore tracker
1 parent 5f1df08 commit 4f9babb

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

Lib/multiprocessing/semaphore_tracker.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ def ensure_running(self):
6060
fds_to_pass.append(sys.stderr.fileno())
6161
except Exception:
6262
pass
63-
cmd = 'from multiprocessing.semaphore_tracker import main;main(%d)'
63+
cmd = 'from multiprocessing.semaphore_tracker import main;main({}, {})'
6464
r, w = os.pipe()
6565
try:
6666
fds_to_pass.append(r)
6767
# process will out live us, so no need to wait on pid
6868
exe = spawn.get_executable()
6969
args = [exe] + util._args_from_interpreter_flags()
70-
args += ['-c', cmd % r]
70+
args += ['-c', cmd.format(r, sys.stderr.fileno())]
7171
pid = util.spawnv_passfds(exe, args, fds_to_pass)
7272
except:
7373
os.close(w)
@@ -105,7 +105,7 @@ def _send(self, cmd, name):
105105
getfd = _semaphore_tracker.getfd
106106

107107

108-
def main(fd):
108+
def main(fd, fd_write):
109109
'''Run semaphore tracker.'''
110110
# protect the process from ^C and "killall python" etc
111111
signal.signal(signal.SIGINT, signal.SIG_IGN)
@@ -128,6 +128,8 @@ def main(fd):
128128
cache.add(name)
129129
elif cmd == b'UNREGISTER':
130130
cache.remove(name)
131+
elif cmd == b'PING':
132+
os.write(fd_write, b"PONG\n")
131133
else:
132134
raise RuntimeError('unrecognized command %r' % cmd)
133135
except Exception:

Lib/test/_test_multiprocessing.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4473,9 +4473,24 @@ def check_semaphore_tracker_death(self, signum, should_die):
44734473
# bpo-31310: if the semaphore tracker process has died, it should
44744474
# be restarted implicitly.
44754475
from multiprocessing.semaphore_tracker import _semaphore_tracker
4476-
_semaphore_tracker.ensure_running()
4477-
pid = _semaphore_tracker._pid
4478-
time.sleep(1.0) # Give time for the child to register the signal handlers
4476+
old_stderr = sys.stderr
4477+
r, w = os.pipe()
4478+
try:
4479+
sys.stderr = open(w, "bw")
4480+
_semaphore_tracker.ensure_running()
4481+
pid = _semaphore_tracker._pid
4482+
# Wait until we receive the PONG from the child, indicating that
4483+
# the signal handlers have been registered. See bpo-33613 for more
4484+
# information.
4485+
_semaphore_tracker._send("PING", "")
4486+
with open(r, "rb") as pipe:
4487+
data = pipe.readline()
4488+
if b"PON" not in data:
4489+
raise ValueError("Invalid data in stderr!")
4490+
finally:
4491+
sys.stderr.close()
4492+
sys.stderr = old_stderr
4493+
44794494
os.kill(pid, signum)
44804495
time.sleep(1.0) # give it time to die
44814496

0 commit comments

Comments
 (0)