From e56608ab9163131724a08dab601511d0c82d9c6f Mon Sep 17 00:00:00 2001 From: David Wilson Date: Sat, 21 Apr 2018 19:39:12 +0100 Subject: [PATCH] parent: don't wait for SIGTERM to complete. --- mitogen/parent.py | 15 +++++++++++---- tests/parent_test.py | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mitogen/parent.py b/mitogen/parent.py index 1173da09..3392f220 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -603,13 +603,20 @@ class Stream(mitogen.core.Stream): return raise + self._reaped = True if pid: LOG.debug('%r: child process exit status was %d', self, status) - else: - LOG.debug('%r: child process still alive, sending SIGTERM', self) + return + + # For processes like sudo we cannot actually send sudo a signal, + # because it is setuid, so this is best-effort only. + LOG.debug('%r: child process still alive, sending SIGTERM', self) + try: os.kill(self.pid, signal.SIGTERM) - os.waitpid(self.pid, 0) - self._reaped = True + except OSError: + e = sys.exc_info()[1] + if e.args[0] != errno.EPERM: + raise def on_disconnect(self, broker): self._reap_child() diff --git a/tests/parent_test.py b/tests/parent_test.py index ec74eb3f..c8c2e876 100644 --- a/tests/parent_test.py +++ b/tests/parent_test.py @@ -10,6 +10,23 @@ import testlib import mitogen.parent +def wait_for_child(pid, timeout=1.0): + deadline = time.time() + timeout + while timeout < time.time(): + try: + target_pid, status = os.waitpid(pid, os.WNOHANG) + if target_pid == pid: + return + except OSError: + e = sys.exc_info()[1] + if e.args[0] == errno.ECHILD: + return + + time.sleep(0.05) + + assert False, "wait_for_child() timed out" + + class ReapChildTest(testlib.RouterMixin, testlib.TestCase): def test_connect_timeout(self): # Ensure the child process is reaped if the connection times out. @@ -24,6 +41,7 @@ class ReapChildTest(testlib.RouterMixin, testlib.TestCase): self.assertRaises(mitogen.core.TimeoutError, lambda: stream.connect() ) + wait_for_child(stream.pid) e = self.assertRaises(OSError, lambda: os.kill(stream.pid, 0) ) @@ -80,6 +98,7 @@ class ContextTest(testlib.RouterMixin, unittest2.TestCase): local = self.router.local() pid = local.call(os.getpid) local.shutdown(wait=True) + wait_for_child(pid) self.assertRaises(OSError, lambda: os.kill(pid, 0))