aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorValentin Lab <valentin.lab@kalysto.org>2025-05-31 09:56:09 +0800
committerDenys Vlasenko <vda.linux@googlemail.com>2025-07-30 19:49:23 +0200
commit41f677ec5daccaeae616a0bbf508d2a2d54bdac7 (patch)
tree678087fc34a44476ce33cb0d141302aa7ae6891b /miscutils
parent427f80873274c9e4d3860a193e6f1e82b0f61997 (diff)
downloadbusybox-w32-41f677ec5daccaeae616a0bbf508d2a2d54bdac7.tar.gz
busybox-w32-41f677ec5daccaeae616a0bbf508d2a2d54bdac7.tar.bz2
busybox-w32-41f677ec5daccaeae616a0bbf508d2a2d54bdac7.zip
crond: reap orphaned grandchildren to prevent zombie buildup
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@kalysto.org> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/crond.c4
1 files changed, 4 insertions, 0 deletions
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)
1001 /* else: r == 0: "process is still running" */ 1001 /* else: r == 0: "process is still running" */
1002 file->cf_has_running = 1; 1002 file->cf_has_running = 1;
1003 } 1003 }
1004
1005 /* Reap any other children we don't actively track */
1006 while (waitpid(-1, NULL, WNOHANG) > 0);
1007
1004//FIXME: if !file->cf_has_running && file->deleted: delete it! 1008//FIXME: if !file->cf_has_running && file->deleted: delete it!
1005//otherwise deleted entries will stay forever, right? 1009//otherwise deleted entries will stay forever, right?
1006 num_still_running += file->cf_has_running; 1010 num_still_running += file->cf_has_running;