From 4ec2e760724b48989cb077a9a11764b0e4273fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20=C5=81ada?= <przlada@gmail.com> Date: Mon, 14 Oct 2024 19:27:02 +0200 Subject: [PATCH 1/2] Extend the "Child process died" log to include `exitcode` and `signal_name` --- uvicorn/supervisors/multiprocess.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/uvicorn/supervisors/multiprocess.py b/uvicorn/supervisors/multiprocess.py index e198fe780..2b2835363 100644 --- a/uvicorn/supervisors/multiprocess.py +++ b/uvicorn/supervisors/multiprocess.py @@ -98,6 +98,10 @@ def join(self) -> None: def pid(self) -> int | None: return self.process.pid + @property + def exitcode(self) -> int | None: + return self.process.exitcode + class Multiprocess: def __init__( @@ -167,13 +171,20 @@ def keep_subprocess_alive(self) -> None: if process.is_alive(): continue + exitcode = process.exitcode process.kill() # process is hung, kill it process.join() if self.should_exit.is_set(): return # pragma: full coverage - logger.info(f"Child process [{process.pid}] died") + signal_name = None + if exitcode is not None and exitcode < 0: + try: + signal_name = signal.Signals(-exitcode).name + except ValueError: + pass + logger.info(f"Child process [{process.pid}] died", extra={"exitcode": exitcode, "signal_name": signal_name}) process = Process(self.config, self.target, self.sockets) process.start() self.processes[idx] = process From 9eef487beda1fdd4f70f7b98967f22c1aea3b4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20=C5=81ada?= <przlada@gmail.com> Date: Mon, 14 Oct 2024 20:39:05 +0200 Subject: [PATCH 2/2] Add # pragma: no cover --- uvicorn/supervisors/multiprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uvicorn/supervisors/multiprocess.py b/uvicorn/supervisors/multiprocess.py index 2b2835363..0cb38bfd1 100644 --- a/uvicorn/supervisors/multiprocess.py +++ b/uvicorn/supervisors/multiprocess.py @@ -182,7 +182,7 @@ def keep_subprocess_alive(self) -> None: if exitcode is not None and exitcode < 0: try: signal_name = signal.Signals(-exitcode).name - except ValueError: + except ValueError: # pragma: no cover pass logger.info(f"Child process [{process.pid}] died", extra={"exitcode": exitcode, "signal_name": signal_name}) process = Process(self.config, self.target, self.sockets)