Fix Graceful shutdown timeout with parent died
This commit is contained in:
@@ -144,16 +144,19 @@ class Service(object):
|
||||
with _exit_on_exception():
|
||||
self.reload()
|
||||
|
||||
def _clean_exit(self, *args, **kwargs):
|
||||
def _terminate(self):
|
||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
||||
if self.graceful_shutdown_timeout > 0:
|
||||
signal.alarm(self.graceful_shutdown_timeout)
|
||||
LOG.info('Caught SIGTERM signal, '
|
||||
'graceful exiting of service %s' % self._title)
|
||||
with _exit_on_exception():
|
||||
self.terminate()
|
||||
sys.exit(0)
|
||||
|
||||
def _clean_exit(self, *args, **kwargs):
|
||||
LOG.info('Caught SIGTERM signal, '
|
||||
'graceful exiting of service %s' % self._title)
|
||||
self._terminate()
|
||||
|
||||
def _graceful_shutdown_timeout_cb(self, signum, frame):
|
||||
LOG.info('Graceful shutdown timeout (%d) exceeded, exiting %s now.' %
|
||||
(self.graceful_shutdown_timeout, self._title))
|
||||
@@ -464,10 +467,7 @@ class ServiceManager(object):
|
||||
if self._current_process is not None:
|
||||
LOG.info('Parent process has died unexpectedly, %s exiting'
|
||||
% self._current_process._title)
|
||||
with _exit_on_exception():
|
||||
self._current_process.terminate()
|
||||
sys.exit(0)
|
||||
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
else:
|
||||
os._exit(0)
|
||||
|
||||
|
||||
@@ -190,6 +190,12 @@ class TestCotyledon(Base):
|
||||
self.assertEqual([
|
||||
b'ERROR:cotyledon.tests.examples:heavy terminate',
|
||||
b'ERROR:cotyledon.tests.examples:heavy terminate',
|
||||
b'INFO:cotyledon:Caught SIGTERM signal, graceful exiting of '
|
||||
b'service heavy(0) [XXXX]',
|
||||
b'INFO:cotyledon:Caught SIGTERM signal, graceful exiting of '
|
||||
b'service heavy(1) [XXXX]',
|
||||
b'INFO:cotyledon:Caught SIGTERM signal, graceful exiting of '
|
||||
b'service light(0) [XXXX]',
|
||||
b'INFO:cotyledon:Parent process has died unexpectedly, '
|
||||
b'heavy(0) [XXXX] exiting',
|
||||
b'INFO:cotyledon:Parent process has died unexpectedly, '
|
||||
@@ -206,7 +212,7 @@ class TestBuggyCotyledon(Base):
|
||||
@unittest.skipIf(sys.version_info[0] != 3,
|
||||
"Buggy on py27, time.sleep returns before alarm callback "
|
||||
"is called")
|
||||
def test_graceful_timeout(self):
|
||||
def test_graceful_timeout_term(self):
|
||||
lines = self.get_lines(1)
|
||||
childpid = self.get_pid(lines[0])
|
||||
self.subp.terminate()
|
||||
@@ -218,10 +224,35 @@ class TestBuggyCotyledon(Base):
|
||||
self.assertNotIn('ERROR:cotyledon.tests.examples:time.sleep done',
|
||||
lines)
|
||||
self.assertEqual([
|
||||
b'INFO:cotyledon:Caught SIGTERM signal, graceful exiting of '
|
||||
b'service buggy(0) [XXXX]',
|
||||
b'INFO:cotyledon:Graceful shutdown timeout (1) exceeded, '
|
||||
b'exiting buggy(0) [XXXX] now.',
|
||||
b'DEBUG:cotyledon:Shutdown finish'
|
||||
], lines[-2:])
|
||||
], lines[-3:])
|
||||
|
||||
@unittest.skipIf(sys.version_info[0] != 3,
|
||||
"Buggy on py27, time.sleep returns before alarm callback "
|
||||
"is called")
|
||||
def test_graceful_timeout_kill(self):
|
||||
lines = self.get_lines(1)
|
||||
childpid = self.get_pid(lines[0])
|
||||
self.subp.kill()
|
||||
time.sleep(2)
|
||||
self.assertEqual(-9, self.subp.poll())
|
||||
self.assertRaises(OSError, os.kill, self.subp.pid, 0)
|
||||
self.assertRaises(OSError, os.kill, childpid, 0)
|
||||
lines = self.hide_pids(self.get_lines())
|
||||
self.assertNotIn('ERROR:cotyledon.tests.examples:time.sleep done',
|
||||
lines)
|
||||
self.assertEqual([
|
||||
b'INFO:cotyledon:Parent process has died unexpectedly, buggy(0) '
|
||||
b'[XXXX] exiting',
|
||||
b'INFO:cotyledon:Caught SIGTERM signal, graceful exiting of '
|
||||
b'service buggy(0) [XXXX]',
|
||||
b'INFO:cotyledon:Graceful shutdown timeout (1) exceeded, '
|
||||
b'exiting buggy(0) [XXXX] now.',
|
||||
], lines[-3:])
|
||||
|
||||
|
||||
class TestOsloCotyledon(Base):
|
||||
|
||||
Reference in New Issue
Block a user