From c22f8804ad2761bcf7bfa459f05228c68f290d03 Mon Sep 17 00:00:00 2001 From: "Hongli Lai (Phusion)" Date: Thu, 13 Feb 2014 15:36:01 +0100 Subject: [PATCH] Correctly reap child processes that are adopted during invocation of init scripts. --- Changelog.md | 4 ++++ image/my_init | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index b273214..2a30988 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,7 @@ +## 0.9.6 + + * Fixed a bug in `my_init`: child processes that have been adopted during execution of init scripts are now properly reaped. + ## 0.9.5 (release date: 2014-02-06) * Environment variables are now no longer reset by runit. This is achieved by running `runsvdir` directly instead of through Debian's `runsvdir-start`. diff --git a/image/my_init b/image/my_init index df2ea9f..faf2381 100755 --- a/image/my_init +++ b/image/my_init @@ -29,8 +29,7 @@ def reap_child(signum, frame): except OSError: pass -def stop_child_process(name): - global pid +def stop_child_process(name, pid): print("*** Shutting down %s (PID %d)..." % (name, pid)) try: os.kill(pid, signal.SIGHUP) @@ -41,15 +40,19 @@ def run_command_killable(*argv): global pid filename = argv[0] pid = os.spawnvp(os.P_NOWAIT, filename, argv) - signal.signal(signal.SIGINT, lambda signum, frame: stop_child_process(filename)) - signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process(filename)) + signal.signal(signal.SIGINT, lambda signum, frame: stop_child_process(filename, pid)) + signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process(filename, pid)) try: - this_pid, status = os.waitpid(pid, 0) - except OSError as e: - if e.errno == errno.EINTR: - sys.exit(2) - else: - raise + done = False + while not done: + try: + this_pid, status = os.waitpid(-1, 0) + done = this_pid == pid + except OSError as e: + if e.errno == errno.EINTR: + sys.exit(2) + else: + raise finally: signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) @@ -74,7 +77,7 @@ signal.signal(signal.SIGCHLD, reap_child) print("*** Booting runit...") pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir", "-P", "/etc/service", "log: %s" % ('.' * 395)) print("*** Runit started as PID %d" % pid) -signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process("runit")) +signal.signal(signal.SIGTERM, lambda signum, frame: stop_child_process("runit", pid)) # Wait for runit, and while waiting, reap any adopted orphans. done = False