From 4744a89c338a5610ce195ec8b330a020d77065a7 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Sun, 18 Dec 2022 14:40:38 +0200 Subject: [PATCH] Fix double ctrl-c kill (#2634) --- sanic/worker/manager.py | 8 ++++---- tests/worker/test_manager.py | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/sanic/worker/manager.py b/sanic/worker/manager.py index e4deaf1e..b2be0318 100644 --- a/sanic/worker/manager.py +++ b/sanic/worker/manager.py @@ -40,7 +40,7 @@ class WorkerManager: self.monitor_publisher, self.monitor_subscriber = monitor_pubsub self.worker_state = worker_state self.worker_state[self.MAIN_IDENT] = {"pid": self.pid} - self.terminated = False + self._shutting_down = False self._serve = serve self._server_settings = server_settings self._server_count = count() @@ -116,10 +116,9 @@ class WorkerManager: self.join() def terminate(self): - if not self.terminated: + if not self._shutting_down: for process in self.processes: process.terminate() - self.terminated = True def restart( self, @@ -257,7 +256,7 @@ class WorkerManager: raise ServerKilled def shutdown_signal(self, signal, frame): - if self.terminated: + if self._shutting_down: logger.info("Shutdown interrupted. Killing.") with suppress(ServerKilled): self.kill() @@ -270,6 +269,7 @@ class WorkerManager: for process in self.processes: if process.is_alive(): process.terminate() + self._shutting_down = True @property def pid(self): diff --git a/tests/worker/test_manager.py b/tests/worker/test_manager.py index 6940c83f..ae5f4592 100644 --- a/tests/worker/test_manager.py +++ b/tests/worker/test_manager.py @@ -33,9 +33,7 @@ def test_terminate(os_mock: Mock): context = Mock() context.Process.return_value = process manager = WorkerManager(1, fake_serve, {}, context, (Mock(), Mock()), {}) - assert manager.terminated is False manager.terminate() - assert manager.terminated is True os_mock.kill.assert_called_once_with(1234, SIGINT) @@ -63,6 +61,24 @@ def test_kill(os_mock: Mock): os_mock.kill.assert_called_once_with(1234, SIGKILL) +@patch("sanic.worker.process.os") +@patch("sanic.worker.manager.os") +def test_shutdown_signal_send_kill( + manager_os_mock: Mock, process_os_mock: Mock +): + process = Mock() + process.pid = 1234 + context = Mock() + context.Process.return_value = process + manager = WorkerManager(1, fake_serve, {}, context, (Mock(), Mock()), {}) + assert manager._shutting_down is False + manager.shutdown_signal(SIGINT, None) + assert manager._shutting_down is True + process_os_mock.kill.assert_called_once_with(1234, SIGINT) + manager.shutdown_signal(SIGINT, None) + manager_os_mock.kill.assert_called_once_with(1234, SIGKILL) + + def test_restart_all(): p1 = Mock() p2 = Mock()