diff options
author | Thomas Moreau <thomas.moreau.2010@gmail.com> | 2019-04-24 19:45:52 (GMT) |
---|---|---|
committer | Antoine Pitrou <antoine@python.org> | 2019-04-24 19:45:52 (GMT) |
commit | 004b93ea8947bcbe85b6fa16fe0999bfa712d5c1 (patch) | |
tree | f878d3c76b355822e4f88bc92f55a6511bd9dd4f /Lib/multiprocessing | |
parent | 09d434caa2c01477ea2ccc3e9b88e9faa0107c61 (diff) | |
download | cpython-004b93ea8947bcbe85b6fa16fe0999bfa712d5c1.zip cpython-004b93ea8947bcbe85b6fa16fe0999bfa712d5c1.tar.gz cpython-004b93ea8947bcbe85b6fa16fe0999bfa712d5c1.tar.bz2 |
bpo-36668: FIX reuse semaphore tracker for child processes (#5172)
Fix the multiprocessing.semaphore_tracker so it is reused by child processes.
Diffstat (limited to 'Lib/multiprocessing')
-rw-r--r-- | Lib/multiprocessing/semaphore_tracker.py | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/Lib/multiprocessing/semaphore_tracker.py b/Lib/multiprocessing/semaphore_tracker.py index 82833bc..3c2c3ad 100644 --- a/Lib/multiprocessing/semaphore_tracker.py +++ b/Lib/multiprocessing/semaphore_tracker.py @@ -44,20 +44,23 @@ class SemaphoreTracker(object): This can be run from any process. Usually a child process will use the semaphore created by its parent.''' with self._lock: - if self._pid is not None: + if self._fd is not None: # semaphore tracker was launched before, is it still running? + if self._check_alive(): + # => still alive + return + # => dead, launch it again + os.close(self._fd) + + # Clean-up to avoid dangling processes. try: - pid, _ = os.waitpid(self._pid, os.WNOHANG) + # _pid can be None if this process is a child from another + # python process, which has started the semaphore_tracker. + if self._pid is not None: + os.waitpid(self._pid, 0) except ChildProcessError: - # The process terminated + # The semaphore_tracker has already been terminated. pass - else: - if not pid: - # => still alive - return - - # => dead, launch it again - os.close(self._fd) self._fd = None self._pid = None @@ -99,6 +102,17 @@ class SemaphoreTracker(object): finally: os.close(r) + def _check_alive(self): + '''Check that the pipe has not been closed by sending a probe.''' + try: + # We cannot use send here as it calls ensure_running, creating + # a cycle. + os.write(self._fd, b'PROBE:0\n') + except OSError: + return False + else: + return True + def register(self, name): '''Register name of semaphore with semaphore tracker.''' self._send('REGISTER', name) @@ -150,6 +164,8 @@ def main(fd): cache.add(name) elif cmd == b'UNREGISTER': cache.remove(name) + elif cmd == b'PROBE': + pass else: raise RuntimeError('unrecognized command %r' % cmd) except Exception: |