diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py index ddbd0c25739..70105158e55 100644 --- a/Lib/multiprocessing/forkserver.py +++ b/Lib/multiprocessing/forkserver.py @@ -150,15 +150,15 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None): util._close_stdin() sig_r, sig_w = os.pipe() + os.set_blocking(sig_r, False) os.set_blocking(sig_w, False) def sigchld_handler(*_unused): - try: - os.write(sig_w, b'.') - except BlockingIOError: - pass + # Dummy signal handler, doesn't do anything + pass # letting SIGINT through avoids KeyboardInterrupt tracebacks + # unblocking SIGCHLD allows the wakeup fd to notify our event loop handlers = { signal.SIGCHLD: sigchld_handler, signal.SIGINT: signal.SIG_DFL, @@ -166,6 +166,9 @@ def sigchld_handler(*_unused): old_handlers = {sig: signal.signal(sig, val) for (sig, val) in handlers.items()} + # calling os.write() in the Python signal handler is racy + signal.set_wakeup_fd(sig_w) + # map child pids to client fds pid_to_fd = {} @@ -252,6 +255,7 @@ def sigchld_handler(*_unused): def _serve_one(child_r, fds, unused_fds, handlers): # close unnecessary stuff and reset signal handlers + signal.set_wakeup_fd(-1) for sig, val in handlers.items(): signal.signal(sig, val) for fd in unused_fds: