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,