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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user