diff options
author | Charles-François Natali <cf.natali@gmail.com> | 2013-10-20 21:23:44 (GMT) |
---|---|---|
committer | Charles-François Natali <cf.natali@gmail.com> | 2013-10-20 21:23:44 (GMT) |
commit | 5121debebf9bd36bc2ace57c6ce714a50c5d064e (patch) | |
tree | 156dab16e317e8e6e34a395269ced6190d56641a | |
parent | e5a3154c6395dc03c964b15011c9ac3aa5b14022 (diff) | |
download | cpython-5121debebf9bd36bc2ace57c6ce714a50c5d064e.zip cpython-5121debebf9bd36bc2ace57c6ce714a50c5d064e.tar.gz cpython-5121debebf9bd36bc2ace57c6ce714a50c5d064e.tar.bz2 |
Issue #19310: asyncio: fix child processes reaping logic.
-rw-r--r-- | Lib/asyncio/unix_events.py | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 7623f78..b4e2699 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -167,23 +167,25 @@ class SelectorEventLoop(selector_events.BaseSelectorEventLoop): def _sig_chld(self): try: - try: - pid, status = os.waitpid(-1, os.WNOHANG) - except ChildProcessError: - return - if pid == 0: - self.call_soon(self._sig_chld) - return - elif os.WIFSIGNALED(status): - returncode = -os.WTERMSIG(status) - elif os.WIFEXITED(status): - returncode = os.WEXITSTATUS(status) - else: - self.call_soon(self._sig_chld) - return - transp = self._subprocesses.get(pid) - if transp is not None: - transp._process_exited(returncode) + # because of signal coalescing, we must keep calling waitpid() as + # long as we're able to reap a child + while True: + try: + pid, status = os.waitpid(-1, os.WNOHANG) + except ChildProcessError: + break + if pid == 0: + break + elif os.WIFSIGNALED(status): + returncode = -os.WTERMSIG(status) + elif os.WIFEXITED(status): + returncode = os.WEXITSTATUS(status) + else: + # shouldn't happen + continue + transp = self._subprocesses.get(pid) + if transp is not None: + transp._process_exited(returncode) except Exception: logger.exception('Unknown exception in SIGCHLD handler') |