Skip to content

Commit e59e82b

Browse files
author
Neha Singla
committed
Fix zombie process accumulation from git operations in cloud environment
Git commands spawn helper processes (git-credential-helper, git-remote-https, ssh) that become zombies when the main git process exits before children complete. This is problematic in cloud/container environments where the application runs as PID 1 or under minimal init systems that don't reliably reap orphaned processes. Added SIGCHLD signal handler to automatically reap zombie processes system-wide using non-blocking waitpid(), preventing resource leaks without affecting normal git operations.
1 parent c5585fd commit e59e82b

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

jupyterlab_git/git.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import tornado.locks
2323
from jupyter_server.utils import ensure_async
2424
from nbdime import diff_notebooks, merge_notebooks
25+
import signal
2526

2627
from .log import get_logger
2728

@@ -55,6 +56,36 @@
5556
execution_lock = tornado.locks.Lock()
5657

5758

59+
def sigchld_handler(signum, frame):
60+
"""Handle SIGCHLD to reap zombie processes from git operations.
61+
62+
Git commands often spawn helper processes (git-credential-helper, git-remote-https,
63+
ssh, git-upload-pack, git-receive-pack) that can become zombie processes when the
64+
main git process exits before its children complete.
65+
66+
This is particularly problematic in cloud/container environments where:
67+
- The application runs as PID 1 or under minimal init systems
68+
- Standard init process zombie reaping may be unreliable or slow
69+
- Resource constraints can cause zombie accumulation
70+
71+
This handler automatically reaps any zombie processes to prevent system resource leaks.
72+
"""
73+
while True:
74+
try:
75+
# Reap child processes non-blockingly
76+
pid, status = os.waitpid(-1, os.WNOHANG)
77+
if pid == 0: # No more children to reap
78+
break
79+
get_logger().debug(f"Reaped child process {pid} with status {status}")
80+
except OSError:
81+
# No child processes or other error
82+
break
83+
84+
85+
# Set up SIGCHLD handler for automatic zombie reaping
86+
signal.signal(signal.SIGCHLD, sigchld_handler)
87+
88+
5889
class State(IntEnum):
5990
"""Git repository state."""
6091

0 commit comments

Comments
 (0)