From 4f74f4a4b87fba6c5b5e9d092d8e75b0153580bb Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 29 Jan 2025 11:57:59 +0530 Subject: [PATCH] fix: fast shutdown (#4) Break the poller wait by using shutdown event to let it know its time to wake up. --- gunicorn/workers/gthread.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gunicorn/workers/gthread.py b/gunicorn/workers/gthread.py index fb3830d4..6eb8838b 100644 --- a/gunicorn/workers/gthread.py +++ b/gunicorn/workers/gthread.py @@ -74,6 +74,7 @@ class ThreadWorker(base.Worker): # initialise the pool self.tpool = None self.poller = None + self.shutdown_event = os.eventfd(1) self._lock = None self.futures = deque() self._keep = deque() @@ -97,6 +98,10 @@ class ThreadWorker(base.Worker): """Override this method to customize how the thread pool is created""" return futures.ThreadPoolExecutor(max_workers=self.cfg.threads) + def handle_exit(self, sig, frame): + self.alive = False + os.eventfd_write(self.shutdown_event, 0) + def handle_quit(self, sig, frame): self.alive = False # worker_int callback @@ -201,6 +206,9 @@ class ThreadWorker(base.Worker): acceptor = partial(self.accept, server) self.poller.register(sock, selectors.EVENT_READ, acceptor) + # This is just used to wake up the poller, nothing else needs to be done. + self.poller.register(self.shutdown_event, selectors.EVENT_READ, lambda *args: None) + while self.alive: # notify the arbiter we are alive self.notify()