diff options
| author | Davanum Srinivas <dims@linux.vnet.ibm.com> | 2012-12-27 12:22:56 -0500 |
|---|---|---|
| committer | Davanum Srinivas <dims@linux.vnet.ibm.com> | 2013-01-02 11:37:36 -0500 |
| commit | ffeb0855085617095f19296770a1223cb5641d1c (patch) | |
| tree | e332b2d402056fa039b0288e1e8b16cb9e831e70 | |
| parent | 8888ad0126f25c91b90f7bc4c2440da0bf35ec1d (diff) | |
| download | oslo-ffeb0855085617095f19296770a1223cb5641d1c.tar.gz oslo-ffeb0855085617095f19296770a1223cb5641d1c.tar.xz oslo-ffeb0855085617095f19296770a1223cb5641d1c.zip | |
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
| -rw-r--r-- | openstack/common/service.py | 9 |
1 files changed, 8 insertions, 1 deletions
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: |
