From 9975b8001f10a8f1e8f15c30360a5b6b3a857f03 Mon Sep 17 00:00:00 2001 From: Maxim Martynov Date: Tue, 20 Jul 2021 00:48:15 +0300 Subject: [PATCH] Avoid zombie processes in case of using LocalProcessSpawner --- jupyterhub/proxy.py | 5 +++-- jupyterhub/spawner.py | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/jupyterhub/proxy.py b/jupyterhub/proxy.py index 5f706970..e30bb032 100644 --- a/jupyterhub/proxy.py +++ b/jupyterhub/proxy.py @@ -722,8 +722,9 @@ class ConfigurableHTTPProxy(Proxy): def _check_process(): status = self.proxy_process.poll() if status is not None: - e = RuntimeError("Proxy failed to start with exit code %i" % status) - raise e from None + with self.proxy_process: + e = RuntimeError("Proxy failed to start with exit code %i" % status) + raise e from None for server in (public_server, api_server): for i in range(10): diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py index c642f2c2..d356b9c7 100644 --- a/jupyterhub/spawner.py +++ b/jupyterhub/spawner.py @@ -1542,8 +1542,11 @@ class LocalProcessSpawner(Spawner): if self.proc is not None: status = self.proc.poll() if status is not None: - # clear state if the process is done - self.clear_state() + # handle SIGCHILD to avoid zombie processes + # and also close stdout/stderr file descriptors + with self.proc: + # clear state if the process is done + self.clear_state() return status # if we resumed from stored state,