Merge "Fixes service startup issue on Windows"

This commit is contained in:
Jenkins 2013-09-04 18:24:24 +00:00 committed by Gerrit Code Review
commit 6b09ecfb6e

View File

@ -43,6 +43,29 @@ CONF = cfg.CONF
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def _sighup_supported():
return hasattr(signal, 'SIGHUP')
def _is_sighup(signo):
return _sighup_supported() and signo == signal.SIGHUP
def _signo_to_signame(signo):
signals = {signal.SIGTERM: 'SIGTERM',
signal.SIGINT: 'SIGINT'}
if _sighup_supported():
signals[signal.SIGHUP] = 'SIGHUP'
return signals[signo]
def _set_signals_handler(handler):
signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGINT, handler)
if _sighup_supported():
signal.signal(signal.SIGHUP, handler)
class Launcher(object): class Launcher(object):
"""Launch one or more services and wait for them to complete.""" """Launch one or more services and wait for them to complete."""
@ -100,16 +123,11 @@ class SignalExit(SystemExit):
class ServiceLauncher(Launcher): class ServiceLauncher(Launcher):
def _handle_signal(self, signo, frame): def _handle_signal(self, signo, frame):
# Allow the process to be killed again and die from natural causes # Allow the process to be killed again and die from natural causes
signal.signal(signal.SIGTERM, signal.SIG_DFL) _set_signals_handler(signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGHUP, signal.SIG_DFL)
raise SignalExit(signo) raise SignalExit(signo)
def handle_signal(self): def handle_signal(self):
signal.signal(signal.SIGTERM, self._handle_signal) _set_signals_handler(self._handle_signal)
signal.signal(signal.SIGINT, self._handle_signal)
signal.signal(signal.SIGHUP, self._handle_signal)
def _wait_for_exit_or_signal(self): def _wait_for_exit_or_signal(self):
status = None status = None
@ -121,9 +139,7 @@ class ServiceLauncher(Launcher):
try: try:
super(ServiceLauncher, self).wait() super(ServiceLauncher, self).wait()
except SignalExit as exc: except SignalExit as exc:
signame = {signal.SIGTERM: 'SIGTERM', signame = _signo_to_signame(exc.signo)
signal.SIGINT: 'SIGINT',
signal.SIGHUP: 'SIGHUP'}[exc.signo]
LOG.info(_('Caught %s, exiting'), signame) LOG.info(_('Caught %s, exiting'), signame)
status = exc.code status = exc.code
signo = exc.signo signo = exc.signo
@ -144,7 +160,7 @@ class ServiceLauncher(Launcher):
while True: while True:
self.handle_signal() self.handle_signal()
status, signo = self._wait_for_exit_or_signal() status, signo = self._wait_for_exit_or_signal()
if signo != signal.SIGHUP: if not _is_sighup(signo):
return status return status
self.restart() self.restart()
@ -167,18 +183,14 @@ class ProcessLauncher(object):
self.handle_signal() self.handle_signal()
def handle_signal(self): def handle_signal(self):
signal.signal(signal.SIGTERM, self._handle_signal) _set_signals_handler(self._handle_signal)
signal.signal(signal.SIGINT, self._handle_signal)
signal.signal(signal.SIGHUP, self._handle_signal)
def _handle_signal(self, signo, frame): def _handle_signal(self, signo, frame):
self.sigcaught = signo self.sigcaught = signo
self.running = False self.running = False
# Allow the process to be killed again and die from natural causes # Allow the process to be killed again and die from natural causes
signal.signal(signal.SIGTERM, signal.SIG_DFL) _set_signals_handler(signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGHUP, signal.SIG_DFL)
def _pipe_watcher(self): def _pipe_watcher(self):
# This will block until the write end is closed when the parent # This will block until the write end is closed when the parent
@ -200,7 +212,8 @@ class ProcessLauncher(object):
raise SignalExit(signal.SIGHUP) raise SignalExit(signal.SIGHUP)
signal.signal(signal.SIGTERM, _sigterm) signal.signal(signal.SIGTERM, _sigterm)
signal.signal(signal.SIGHUP, _sighup) if _sighup_supported():
signal.signal(signal.SIGHUP, _sighup)
# Block SIGINT and let the parent send us a SIGTERM # Block SIGINT and let the parent send us a SIGTERM
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN)
@ -211,9 +224,7 @@ class ProcessLauncher(object):
try: try:
launcher.wait() launcher.wait()
except SignalExit as exc: except SignalExit as exc:
signame = {signal.SIGTERM: 'SIGTERM', signame = _signo_to_signame(exc.signo)
signal.SIGINT: 'SIGINT',
signal.SIGHUP: 'SIGHUP'}[exc.signo]
LOG.info(_('Caught %s, exiting'), signame) LOG.info(_('Caught %s, exiting'), signame)
status = exc.code status = exc.code
signo = exc.signo signo = exc.signo
@ -269,7 +280,7 @@ class ProcessLauncher(object):
while True: while True:
self._child_process_handle_signal() self._child_process_handle_signal()
status, signo = self._child_wait_for_exit_or_signal(launcher) status, signo = self._child_wait_for_exit_or_signal(launcher)
if signo != signal.SIGHUP: if not _is_sighup(signo):
break break
launcher.restart() launcher.restart()
@ -339,11 +350,9 @@ class ProcessLauncher(object):
self.handle_signal() self.handle_signal()
self._respawn_children() self._respawn_children()
if self.sigcaught: if self.sigcaught:
signame = {signal.SIGTERM: 'SIGTERM', signame = _signo_to_signame(self.sigcaught)
signal.SIGINT: 'SIGINT',
signal.SIGHUP: 'SIGHUP'}[self.sigcaught]
LOG.info(_('Caught %s, stopping children'), signame) LOG.info(_('Caught %s, stopping children'), signame)
if self.sigcaught != signal.SIGHUP: if not _is_sighup(self.sigcaught):
break break
for pid in self.children: for pid in self.children: