From b9a857003929be9900c2f2baa9ea4d47d0bc3c22 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 3 Feb 2025 11:15:01 +0530 Subject: [PATCH] fix: Drain shutdown event (#5) Otherwise it goes in a spinny loop --- gunicorn/workers/gthread.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gunicorn/workers/gthread.py b/gunicorn/workers/gthread.py index 6eb8838b..c1af9261 100644 --- a/gunicorn/workers/gthread.py +++ b/gunicorn/workers/gthread.py @@ -74,7 +74,7 @@ class ThreadWorker(base.Worker): # initialise the pool self.tpool = None self.poller = None - self.shutdown_event = os.eventfd(1) + self.shutdown_event = os.eventfd(0) self._lock = None self.futures = deque() self._keep = deque() @@ -100,7 +100,7 @@ class ThreadWorker(base.Worker): def handle_exit(self, sig, frame): self.alive = False - os.eventfd_write(self.shutdown_event, 0) + os.eventfd_write(self.shutdown_event, 1) def handle_quit(self, sig, frame): self.alive = False @@ -154,6 +154,10 @@ class ThreadWorker(base.Worker): # submit the connection to a worker self.enqueue_req(conn) + def on_shutdown_event(self, *args): + # Drain any readable input to avoid getting polled again + _ = os.eventfd_read(self.shutdown_event) + def murder_keepalived(self): now = time.time() while True: @@ -207,7 +211,7 @@ class ThreadWorker(base.Worker): 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) + self.poller.register(self.shutdown_event, selectors.EVENT_READ, self.on_shutdown_event) while self.alive: # notify the arbiter we are alive