From baea1c80e7f23d1cf83b740839586d55ae2c2833 Mon Sep 17 00:00:00 2001 From: Jeroen Pulles Date: Thu, 1 Feb 2024 15:18:26 +0100 Subject: [PATCH] reorganize the log handling in arbiter's reap workers method. --- gunicorn/arbiter.py | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 0eeab392d..ade4e5de2 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -522,32 +522,40 @@ def reap_workers(self): # A worker was terminated. If the termination reason was # that it could not boot, we'll shut it down to avoid # infinite start/stop cycles. - exitcode = status >> 8 + + exitcode = os.WEXITSTATUS(status) \ + if os.WIFEXITED(status) else 0 + + signum = os.WTERMSIG(status) \ + if os.WIFSIGNALED(status) else 0 + try: + sig_name = signal.Signals(signum).name + except ValueError: + sig_name = str(signum) + if exitcode != 0: - self.log.error("Worker (pid:%s) exited with code %s", - wpid, exitcode) + self.log.error("Child exited with code %s (pid: %s)", + exitcode, wpid) + elif signum in (0, signal.SIGTERM): + # 0: as seen from macos/py311 from reload on workers + # where workers from SIGTERM but waitpid/nohang gives + # me 0. + self.log.info("Child terminated (pid: %s)", wpid) + else: + # If the exit code of the worker is 0 and the status + # is greater than 0, then it was most likely killed + # via a signal. + self.log.error("Child exited from signal %s (pid: %s)", + sig_name, wpid) + if exitcode == self.WORKER_BOOT_ERROR: reason = "Worker failed to boot." raise HaltServer(reason, self.WORKER_BOOT_ERROR) + if exitcode == self.APP_LOAD_ERROR: reason = "App failed to load." raise HaltServer(reason, self.APP_LOAD_ERROR) - if exitcode == 0 and status > 0: - # If the exit code of the worker is 0 and the status - # is greater than 0, then it was most likely killed - # via a signal. - try: - sig_name = signal.Signals(status).name - except ValueError: - sig_name = "code {}".format(status) - msg = "Worker (pid:%s) was sent %s!" - - # Additional hint for SIGKILL - if status == signal.SIGKILL: - msg += " Perhaps out of memory?" - self.log.error(msg, wpid, sig_name) - worker = self.WORKERS.pop(wpid, None) if not worker: continue