From ffeb0855085617095f19296770a1223cb5641d1c Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Thu, 27 Dec 2012 12:22:56 -0500 Subject: Don't rely on os.wait() blocking Before this fix which was included in eventlet 0.10.0: https://bitbucket.org/which_linden/eventlet/issue/92/eventletgreen-override-of-oswaitpid the os.wait() wrapper in eventlet would not block if no child processes had exited. This was clearly buggy behaviour and os.wait() no blocks correctly. However, it appears it now does not return if the parent process was interrupted by a signal. This means that you can't kill the parent process and have the child processes cleaned up gracefully. To avoid all these issues, switch to non-blocking wait behaviour. We use WNOHANG with waitpid() to poll for an exited child process and, if there is none, we yield to other green threads and sleep for a short period. This means excessive CPU usage, though, which will be tracked by bug #1095346. Check pid to avoid some unnecessary warning/info messages in the logs Fixes LP #1094076 Change-Id: I783fac652376c2daa9d591403b9f4c1fe9523043 --- openstack/common/service.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'openstack') diff --git a/openstack/common/service.py b/openstack/common/service.py index 0df0dec..740378f 100644 --- a/openstack/common/service.py +++ b/openstack/common/service.py @@ -243,7 +243,10 @@ class ProcessLauncher(object): def _wait_child(self): try: - pid, status = os.wait() + # Don't block if no child processes have exited + pid, status = os.waitpid(0, os.WNOHANG) + if not pid: + return None except OSError as exc: if exc.errno not in (errno.EINTR, errno.ECHILD): raise @@ -275,6 +278,10 @@ class ProcessLauncher(object): while self.running: wrap = self._wait_child() if not wrap: + # Yield to other threads if no children have exited + # Sleep for a short time to avoid excessive CPU usage + # (see bug #1095346) + eventlet.greenthread.sleep(.01) continue while self.running and len(wrap.children) < wrap.workers: -- cgit