diff options
| author | Valentin Lab <valentin.lab@kalysto.org> | 2025-05-31 09:56:09 +0800 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-07-30 19:49:23 +0200 |
| commit | 41f677ec5daccaeae616a0bbf508d2a2d54bdac7 (patch) | |
| tree | 678087fc34a44476ce33cb0d141302aa7ae6891b /miscutils | |
| parent | 427f80873274c9e4d3860a193e6f1e82b0f61997 (diff) | |
| download | busybox-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.c | 4 |
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; |
