From 028809f769b36a4fb770374bb2901474b593bc18 Mon Sep 17 00:00:00 2001 From: Terry Wilson Date: Wed, 6 Mar 2024 15:55:47 -0600 Subject: [PATCH] Make signal handling order predictable Due to the unordered nature of sets, it is possible for signal handlers like _gracefull_shutdown() to run first and clear the _signal_handlers before other registered handlers have run. This patch converts _signal_handlers from a set to a list and then runs the handlers LIFO similar to how atexit functions are run. Given that the handlers added in service.py are added after clearing the signal_handlers, they are guaranteed to be the first in the list and the last run. Change-Id: Ief3ab2f56fa3d805296709e12e5f7a71560f7b6e Closes-Bug: #2057809 Related-Bug: #2056366 Signed-off-by: Terry Wilson (cherry picked from commit d026081ca44ad7d48cd4cceeb6df767512910d96) --- oslo_service/service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/oslo_service/service.py b/oslo_service/service.py index 107a5ddb..416ad59e 100644 --- a/oslo_service/service.py +++ b/oslo_service/service.py @@ -142,7 +142,7 @@ class SignalHandler(metaclass=Singleton): self.signals_to_name = dict( (sigval, name) for (name, sigval) in self._signals_by_name.items()) - self._signal_handlers = collections.defaultdict(set) + self._signal_handlers = collections.defaultdict(list) self.clear() def clear(self): @@ -158,7 +158,7 @@ class SignalHandler(metaclass=Singleton): if not self.is_signal_supported(sig): return signo = self._signals_by_name[sig] - self._signal_handlers[signo].add(handler) + self._signal_handlers[signo].append(handler) signal.signal(signo, self._handle_signal) def _handle_signal(self, signo, frame): @@ -237,7 +237,7 @@ class SignalHandler(metaclass=Singleton): self.__hub_module_file = sys.modules[hub.__module__].__file__ def _handle_signal_cb(self, signo, frame): - for handler in self._signal_handlers[signo]: + for handler in reversed(self._signal_handlers[signo]): handler(signo, frame) def is_signal_supported(self, sig_name):