From b05ee3d224c5fbbfb8655d93fb7a1e99e6d7eac4 Mon Sep 17 00:00:00 2001 From: Jason Madden <jamadden@gmail.com> Date: Tue, 1 Sep 2015 09:07:59 -0500 Subject: [PATCH] Make waitpid(-1) work properly with exited children. --- gevent/os.py | 14 ++++++++++++-- greentest/test__monkey_sigchld.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/gevent/os.py b/gevent/os.py index 7314689f..befac1e7 100644 --- a/gevent/os.py +++ b/gevent/os.py @@ -238,8 +238,18 @@ if hasattr(os, 'fork'): """ # XXX Does not handle tracing children if pid <= 0: - # magic functions for multiple children. Pass. - return _waitpid(pid, options) + # magic functions for multiple children. + if pid == -1: + # Any child. If we have one that we're watching and that finished, + # we need to use that one. Otherwise, let the OS take care of it. + for k, v in _watched_children.items(): + if isinstance(v, tuple): + pid = k + break + if pid <= 0: + # If we didn't find anything, go to the OS. Otherwise, + # handle waiting + return _waitpid(pid, options) if pid in _watched_children: # yes, we're watching it diff --git a/greentest/test__monkey_sigchld.py b/greentest/test__monkey_sigchld.py index c74b1e53..5d22e473 100644 --- a/greentest/test__monkey_sigchld.py +++ b/greentest/test__monkey_sigchld.py @@ -1,3 +1,4 @@ +import errno import os import sys #os.environ['GEVENT_NOWAITPID'] = 'True' @@ -34,6 +35,15 @@ if hasattr(signal, 'SIGCHLD'): with gevent.Timeout(1): while awaiting_child: gevent.sleep(0.01) + # We should now be able to waitpid() for an arbitrary child + wpid, status = os.waitpid(-1, os.WNOHANG) + assert wpid == pid + # And a second call should raise ECHILD + try: + wpid, status = os.waitpid(-1, os.WNOHANG) + raise AssertionError("Should not be able to wait again") + except OSError as e: + assert e.errno == errno.ECHILD sys.exit(0) else: print("No SIGCHLD, not testing") -- 2.30.9