Revert "Optimization of waiting subprocesses in ProcessLauncher"

This reverts commit bf92010cc9d4c2876eaf6092713aafa94dcc8b35.

Although this change optimized waiting for children processes
to exit, it completely breaks neutron-server due to the following
reasons:

    1. In neutron-server eventlet monkey-patching is done in parent
    process. That is why os.waitpid(0, 0) in _wait_child method also
    gets monkey-patched and eventlet goes crazy. Connecting to parent
    process with strace shows that os.waitpid(0, os.WNOHANG) is
    called, yet it is difficult to say what is really happening
    because the process does not react on termination signals
    (SIGTERM, SIGHUP, SIGINT).

    2. Due to the fact that neutron-server initializes two instances
    of ProcessLauncher in one parent process, calling
    eventlet.greenthread.sleep(self.wait_interval) seems to be the
    only way for the process to switch contexts and allow another
    instance of ProcessLauncher to call _wait_child.

This revert is supposed to be temporary until the way neutron
launches services is reworked.

Conflicts:
	openstack/common/service.py

Related-Bug: #1438321
Change-Id: I5c75c4bf5f060e5d345fe4800bc92f5b4ed9206e
This commit is contained in:
Elena Ezhova
2015-03-30 16:52:52 +03:00
parent 1f7eaf7a8c
commit d465969819

View File

@@ -206,12 +206,16 @@ class ProcessLauncher(object):
for handler in cls._signal_handlers_set:
handler(*args, **kwargs)
def __init__(self):
"""Constructor."""
def __init__(self, wait_interval=0.01):
"""Constructor.
:param wait_interval: The interval to sleep for between checks
of child process exit.
"""
self.children = {}
self.sigcaught = None
self.running = True
self.wait_interval = wait_interval
rfd, self.writepipe = os.pipe()
self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r')
self.handle_signal()
@@ -337,8 +341,8 @@ class ProcessLauncher(object):
def _wait_child(self):
try:
# Block while any of child processes have exited
pid, status = os.waitpid(0, 0)
# 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:
@@ -367,6 +371,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(self.wait_interval)
continue
while self.running and len(wrap.children) < wrap.workers:
self._start_child(wrap)