diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2025-01-19 16:27:04 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2025-01-19 16:27:04 -0800 |
commit | 85547b0f0c608330f411863f688e8da61a22bb89 (patch) | |
tree | 277e8120a12e0fb4622e63d5151c722be3d364de | |
parent | ba3653f6e500f32385f766e308264357631db8b5 (diff) |
vmon: implement --reaper
This adds minimal support for becoming a child subreaper.
Exited orphans are handled correctly by being identified and
ignored without triggering SIGCHLD snapshots nor exiting vmon.
A subsequent commit will make vmon monitor itself as the root pid
when reaper mode is active and vmon is parent of the command
being executed, making it possible to observe any orphans vmon
inherits as subreaper.
-rw-r--r-- | src/vmon.c | 45 |
1 files changed, 34 insertions, 11 deletions
@@ -711,6 +711,13 @@ static vmon_t * vmon_startup(int argc, const char * const *argv) } } + if (vmon->reaper) { + if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long)1) < 0) { + VWM_ERROR("unable become child subreaper: %s", strerror(errno)); + goto _err_win; + } + } + return vmon; _err_win: @@ -919,20 +926,36 @@ int main(int argc, const char * const *argv) vmon->done = 1; } - if (got_sigchld) { - int status, r; - - if (vmon->snapshot && (r = vmon_snapshot(vmon)) < 0) - VWM_ERROR("error saving snapshot: %s", strerror(-r)); + while (got_sigchld) { + int status; + pid_t reaped; got_sigchld = 0; - wait(&status); - - if (WIFEXITED(status)) { - ret = WEXITSTATUS(status); + /* exhaustively collect statuses for all the exited children, if another + * sigchld gets delivered while we're doing this, we'll do it again, until + * that stops. + */ + while ((reaped = waitpid(-1, &status, WNOHANG)) > 0) { + int r; + + /* potential exited orphans if we're being subreaper, ignore those */ + if (reaped != vmon->pid) + continue; + + if (WIFEXITED(status) || WIFSIGNALED(status)) { + if (vmon->snapshot && (r = vmon_snapshot(vmon)) < 0) + VWM_ERROR("error saving snapshot: %s", strerror(-r)); + + ret = WEXITSTATUS(status); + + if (!vmon->linger) + vmon->done = 1; + } + } - if (!vmon->linger) - vmon->done = 1; + if (reaped < 0) { + VWM_ERROR("failed to waitpid on SIGCHLD: %s", strerror(errno)); + vmon->done = 1; } } |