From 9bfbb297634d681bba159737eddba19bd06cd02b Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Tue, 6 Oct 2020 18:05:17 -0700 Subject: [PATCH] =?UTF-8?q?queue=5Fprocessors:=20Use=20try=E2=80=A6finally?= =?UTF-8?q?=20to=20prevent=20leaking=20an=20alarm.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, if consume_func raised an exception for any reason *other* than the alarm being fired, the still-pending alarm would have fired later at some arbitrary point in the calling code. We need two try…finally blocks in case the signal arrives just before signal.alarm(0). Signed-off-by: Anders Kaseorg --- zerver/worker/queue_processors.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/zerver/worker/queue_processors.py b/zerver/worker/queue_processors.py index 27a6f8f5bc..f143aaa18d 100644 --- a/zerver/worker/queue_processors.py +++ b/zerver/worker/queue_processors.py @@ -263,10 +263,18 @@ class QueueProcessingWorker(ABC): time_start = time.time() if self.MAX_CONSUME_SECONDS and self.ENABLE_TIMEOUTS: - signal.signal(signal.SIGALRM, functools.partial(timer_expired, self.MAX_CONSUME_SECONDS, len(events))) - signal.alarm(self.MAX_CONSUME_SECONDS * len(events)) - consume_func(events) - signal.alarm(0) + try: + signal.signal( + signal.SIGALRM, + functools.partial(timer_expired, self.MAX_CONSUME_SECONDS, len(events)), + ) + try: + signal.alarm(self.MAX_CONSUME_SECONDS * len(events)) + consume_func(events) + finally: + signal.alarm(0) + finally: + signal.signal(signal.SIGALRM, signal.SIG_DFL) else: consume_func(events) consume_time_seconds = time.time() - time_start