[git commit] crond: reap orphaned grandchildren to prevent zombie buildup

Denys Vlasenko vda.linux at googlemail.com
Wed Jul 30 17:49:23 UTC 2025


commit: https://git.busybox.net/busybox/commit/?id=41f677ec5daccaeae616a0bbf508d2a2d54bdac7
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

If a cron job launches a background task, e.g. `sh -c "sleep 5 &"`,
the shell exits immediately and the `sleep` process is re-parented to
PID 1.  When BusyBox `crond` itself happens to be PID 1 (common in a
minimal container), those orphans become direct children of `crond`.
Because `crond` only calls waitpid() for the PIDs it explicitly tracks,
these processes remain forever in Z state and the container slowly
fills with zombies.

Add a small `while (waitpid(-1, NULL, WNOHANG) > 0)` sweep at the end
of check_completions() so any stray children are reaped.  When `crond`
is not PID 1 the loop returns -ECHILD immediately, so behaviour and
overhead on a normal system are unchanged.

Size impact: +12 bytes on x86-64 (gcc 13.3.0 -Os, static)

Signed-off-by: Valentin Lab <valentin.lab at kalysto.org>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/crond.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/miscutils/crond.c b/miscutils/crond.c
index 96131cae4..b29745576 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -1001,6 +1001,10 @@ static int check_completions(void)
 			/* else: r == 0: "process is still running" */
 			file->cf_has_running = 1;
 		}
+
+		/* Reap any other children we don't actively track */
+		while (waitpid(-1, NULL, WNOHANG) > 0);
+
 //FIXME: if !file->cf_has_running && file->deleted: delete it!
 //otherwise deleted entries will stay forever, right?
 		num_still_running += file->cf_has_running;


More information about the busybox-cvs mailing list