Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Added graceful argument on Service.stop method
Browse files Browse the repository at this point in the history
This change adds a graceful shutdown arugment to the Service.stop
method in order to allow a service to gracefully wait for threads to
shutdown. Since threadgroup already supports a graceful shutdown
argument for its stop() method, it is trivial to support.

Added unit tests to demonstrate the expected behavior between graceful
and ungraceful service stop()s.

Change-Id: Ibc0df09daef5e2a07f232543f44f2fc4d203511c
Closes-Bug: 1406638
  • Loading branch information
ClifHouck committed Dec 30, 2014
1 parent aa2bcff commit 442fc22
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
4 changes: 2 additions & 2 deletions openstack/common/service.py
Expand Up @@ -434,8 +434,8 @@ def reset(self):
def start(self):
pass

def stop(self):
self.tg.stop()
def stop(self, graceful=False):
self.tg.stop(graceful)
self.tg.wait()
# Signal that service cleanup is done:
if not self._done.ready():
Expand Down
36 changes: 35 additions & 1 deletion tests/unit/test_service.py
Expand Up @@ -273,7 +273,6 @@ def stop(self):


class LauncherTest(test_base.BaseTestCase):

def setUp(self):
super(LauncherTest, self).setUp()
self.mox = self.useFixture(moxstubout.MoxStubout()).mox
Expand Down Expand Up @@ -387,3 +386,38 @@ def test_stop(self):
self.assertEqual([mock.call(22, signal.SIGTERM),
mock.call(222, signal.SIGTERM)],
mock_kill.mock_calls)


class GracefulShutdownTestService(service.Service):
def __init__(self):
super(GracefulShutdownTestService, self).__init__()
self.finished_task = event.Event()

def start(self, sleep_amount):
def sleep_and_send(finish_event):
time.sleep(sleep_amount)
finish_event.send()
self.tg.add_thread(sleep_and_send, self.finished_task)


def exercise_graceful_test_service(sleep_amount, time_to_wait, graceful):
svc = GracefulShutdownTestService()
svc.start(sleep_amount)
svc.stop(graceful)

def wait_for_task(svc):
svc.finished_task.wait()

return eventlet.timeout.with_timeout(time_to_wait, wait_for_task,
svc=svc, timeout_value="Timeout!")


class ServiceTest(test_base.BaseTestCase):
def test_graceful_stop(self):
# Here we wait long enough for the task to gracefully finish.
self.assertEqual(None, exercise_graceful_test_service(1, 2, True))

def test_ungraceful_stop(self):
# Here we stop ungracefully, and will never see the task finish.
self.assertEqual("Timeout!",
exercise_graceful_test_service(1, 2, False))

0 comments on commit 442fc22

Please sign in to comment.