From 3c6789fb8ba87810a2aa83eebf6eea10c969db6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 26 Dec 2020 01:26:54 +0100 Subject: [PATCH] reaper: add optional callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When calling ‘reaper_add()’, the caller can provide a callback. If non-NULL, the reaper will call the callback to handle the actual reaping. If the callback is NULL, or if it returns false, the reaper reaps the child process. --- reaper.c | 54 +++++++++++++++++++++++++++++++++++------------------- reaper.h | 5 ++++- spawn.c | 2 +- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/reaper.c b/reaper.c index 04a444f1..8ebd31a4 100644 --- a/reaper.c +++ b/reaper.c @@ -11,10 +11,16 @@ #include "log.h" #include "tllist.h" +struct child { + pid_t pid; + reaper_cb cb; + void *cb_data; +}; + struct reaper { struct fdm *fdm; int fd; - tll(pid_t) children; + tll(struct child) children; }; static bool fdm_reap(struct fdm *fdm, int fd, int events, void *data); @@ -84,10 +90,12 @@ reaper_destroy(struct reaper *reaper) } void -reaper_add(struct reaper *reaper, pid_t pid) +reaper_add(struct reaper *reaper, pid_t pid, reaper_cb cb, void *cb_data) { LOG_DBG("adding pid=%d", pid); - tll_push_back(reaper->children, pid); + tll_push_back( + reaper->children, + ((struct child){.pid = pid, .cb = cb, .cb_data = cb_data})); } static bool @@ -119,26 +127,34 @@ fdm_reap(struct fdm *fdm, int fd, int events, void *data) } tll_foreach(reaper->children, it) { - /* Don't use wait() since we don't want to accidentally reap - * the PTS slave */ + struct child *child = &it->item; + pid_t pid = child->pid; - pid_t pid = it->item; - - int result; - int res = waitpid(pid, &result, WNOHANG); - - if (res <= 0) { - if (res < 0) - LOG_ERRNO("waitpid failed for pid=%d", pid); + if (pid != (pid_t)info.ssi_pid) continue; + + bool reap_ourselves = true; + if (child->cb != NULL) + reap_ourselves = !child->cb(reaper, pid, child->cb_data); + + if (reap_ourselves) { + int result; + int res = waitpid(pid, &result, WNOHANG); + + if (res <= 0) { + if (res < 0) + LOG_ERRNO("waitpid failed for pid=%d", pid); + continue; + } + + else if (WIFEXITED(result)) + LOG_DBG("pid=%d: exited with status=%d", pid, WEXITSTATUS(result)); + else if (WIFSIGNALED(result)) + LOG_DBG("pid=%d: killed by signal=%d", pid, WTERMSIG(result)); + else + LOG_DBG("pid=%d: died of unknown resason", pid); } - else if (WIFEXITED(result)) - LOG_DBG("pid=%d: exited with status=%d", pid, WEXITSTATUS(result)); - else if (WIFSIGNALED(result)) - LOG_DBG("pid=%d: killed by signal=%d", pid, WTERMSIG(result)); - else - LOG_DBG("pid=%d: died of unknown resason", pid); tll_remove(reaper->children, it); } diff --git a/reaper.h b/reaper.h index 2daa9a8b..f955aa44 100644 --- a/reaper.h +++ b/reaper.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "fdm.h" @@ -9,4 +10,6 @@ struct reaper; struct reaper *reaper_init(struct fdm *fdm); void reaper_destroy(struct reaper *reaper); -void reaper_add(struct reaper *reaper, pid_t pid); +typedef bool (*reaper_cb)(struct reaper *reaper, pid_t pid, void *data); + +void reaper_add(struct reaper *reaper, pid_t pid, reaper_cb cb, void *cb_data); diff --git a/spawn.c b/spawn.c index cc4755f4..6d96cf54 100644 --- a/spawn.c +++ b/spawn.c @@ -55,7 +55,7 @@ spawn(struct reaper *reaper, const char *cwd, char *const argv[], close(pipe_fds[0]); if (ret == 0) { - reaper_add(reaper, pid); + reaper_add(reaper, pid, NULL, NULL); return true; } else if (ret < 0) { LOG_ERRNO("failed to read from pipe");