summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2025-01-19 16:27:04 -0800
committerVito Caputo <vcaputo@pengaru.com>2025-01-19 16:27:04 -0800
commit85547b0f0c608330f411863f688e8da61a22bb89 (patch)
tree277e8120a12e0fb4622e63d5151c722be3d364de
parentba3653f6e500f32385f766e308264357631db8b5 (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.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/vmon.c b/src/vmon.c
index 059bcd5..347d5d3 100644
--- a/src/vmon.c
+++ b/src/vmon.c
@@ -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;
}
}
© All Rights Reserved