diff options
author | Antoine Pitrou <pitrou@free.fr> | 2017-11-03 12:59:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-03 12:59:43 (GMT) |
commit | 019c99f325287741d1e0eefeef2b75c8e00b884f (patch) | |
tree | 7bd7d25a44ffe1c6c1ee2d09d8845798cc622bf9 /Lib/multiprocessing/forkserver.py | |
parent | 5fbe5e161c969bc8a0d44a301152f8bf5afe0fc7 (diff) | |
download | cpython-019c99f325287741d1e0eefeef2b75c8e00b884f.zip cpython-019c99f325287741d1e0eefeef2b75c8e00b884f.tar.gz cpython-019c99f325287741d1e0eefeef2b75c8e00b884f.tar.bz2 |
[3.6] bpo-31308: If multiprocessing's forkserver dies, launch it again when necessary (GH-3246) (#4252)
* bpo-31308: If multiprocessing's forkserver dies, launch it again when necessary.
* Fix test on Windows
* Add NEWS entry
* Adopt a different approach: ignore SIGINT and SIGTERM, as in semaphore tracker.
* Fix comment
* Make sure the test doesn't muck with process state
* Also test previously-started processes
* Update 2017-08-30-17-59-36.bpo-31308.KbexyC.rst
* Avoid masking SIGTERM in forkserver. It's not necessary and causes a race condition in test_many_processes..
(cherry picked from commit fc6b348b12ad401cab0261b7b71a65c60a08c0a8)
Diffstat (limited to 'Lib/multiprocessing/forkserver.py')
-rw-r--r-- | Lib/multiprocessing/forkserver.py | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py index d5ce625..fd19895 100644 --- a/Lib/multiprocessing/forkserver.py +++ b/Lib/multiprocessing/forkserver.py @@ -33,6 +33,7 @@ class ForkServer(object): def __init__(self): self._forkserver_address = None self._forkserver_alive_fd = None + self._forkserver_pid = None self._inherited_fds = None self._lock = threading.Lock() self._preload_modules = ['__main__'] @@ -89,8 +90,17 @@ class ForkServer(object): ''' with self._lock: semaphore_tracker.ensure_running() - if self._forkserver_alive_fd is not None: - return + if self._forkserver_pid is not None: + # forkserver was launched before, is it still running? + pid, status = os.waitpid(self._forkserver_pid, os.WNOHANG) + if not pid: + # still alive + return + # dead, launch it again + os.close(self._forkserver_alive_fd) + self._forkserver_address = None + self._forkserver_alive_fd = None + self._forkserver_pid = None cmd = ('from multiprocessing.forkserver import main; ' + 'main(%d, %d, %r, **%r)') @@ -127,6 +137,7 @@ class ForkServer(object): os.close(alive_r) self._forkserver_address = address self._forkserver_alive_fd = alive_w + self._forkserver_pid = pid # # @@ -149,11 +160,11 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None): util._close_stdin() - # ignoring SIGCHLD means no need to reap zombie processes; - # letting SIGINT through avoids KeyboardInterrupt tracebacks handlers = { + # no need to reap zombie processes; signal.SIGCHLD: signal.SIG_IGN, - signal.SIGINT: signal.SIG_DFL, + # protect the process from ^C + signal.SIGINT: signal.SIG_IGN, } old_handlers = {sig: signal.signal(sig, val) for (sig, val) in handlers.items()} |