mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-17 05:33:52 -04:00
reaper: add optional callback
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.
This commit is contained in:
parent
6f3c30ded8
commit
c28bba7a55
3 changed files with 40 additions and 21 deletions
54
reaper.c
54
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue