From ba2175979c923bd7b1630a5bc45d21dc5625ca10 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Fri, 14 Aug 2020 18:38:14 -0400 Subject: Reap children --- service.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 7 deletions(-) (limited to 'service.c') diff --git a/service.c b/service.c index 290372d..35d15f3 100644 --- a/service.c +++ b/service.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,14 @@ err: return -1; } +static void setDeadline(struct Service *service) { + clock_gettime(CLOCK_MONOTONIC_FAST, &service->restartDeadline); + timespecadd( + &service->restartDeadline, &service->restartInterval, + &service->restartDeadline + ); +} + void serviceStart(struct Service *service) { if (service->state != Stop) return; @@ -118,11 +127,7 @@ void serviceStart(struct Service *service) { } else { service->restartInterval = restartInterval; } - clock_gettime(CLOCK_MONOTONIC_FAST, &service->restartDeadline); - timespecadd( - &service->restartDeadline, &service->restartInterval, - &service->restartDeadline - ); + setDeadline(service); service->intent = Start; service->pid = fork(); @@ -131,6 +136,10 @@ void serviceStart(struct Service *service) { return; } if (service->pid) { + syslog( + LOG_INFO, "%s[%jd] start", + service->name, (intmax_t)service->pid + ); service->state = Start; return; } @@ -172,8 +181,8 @@ void serviceSignal(struct Service *service, int signal) { int error = kill(service->pid, signal); if (error) { syslog( - LOG_ERR, "signal %s %s[%ju]: %m", - sys_signame[signal], service->name, (uintmax_t)service->pid + LOG_ERR, "kill(%s[%jd], %s): %m", + service->name, (intmax_t)service->pid, sys_signame[signal] ); } } @@ -191,3 +200,52 @@ void serviceRestart(struct Service *service) { serviceStart(service); } } + +void serviceReap(pid_t pid, int status) { + struct Service *service = NULL; + for (size_t i = 0; i < services.len; ++i) { + if (services.ptr[i].state != Start) continue; + if (services.ptr[i].pid != pid) continue; + service = &services.ptr[i]; + break; + } + if (!service) { + syslog(LOG_WARNING, "reaping unknown child %jd", (intmax_t)pid); + return; + } + + // TODO: Flush line buffers. + + service->state = Stop; + if (WIFEXITED(status)) { + int exit = WEXITSTATUS(status); + if (exit == StopExit || setTest(&stopExits, exit)) { + service->intent = Stop; + } + if (exit) { + syslog( + LOG_WARNING, "%s[%jd] exit %d", + service->name, (intmax_t)pid, exit + ); + } + } else if (WIFSIGNALED(status)) { + syslog( + LOG_WARNING, "%s[%jd] signal %s", + service->name, (intmax_t)pid, sys_signame[WTERMSIG(status)] + ); + } + + if (service->intent == Start) { + setDeadline(service); + syslog( + LOG_INFO, "%s[%jd] restart in %jds", + service->name, (intmax_t)pid, + (intmax_t)service->restartInterval.tv_sec + ); + } else { + syslog(LOG_INFO, "%s[%jd] stop", service->name, (intmax_t)pid); + } + if (service->intent == Restart) { + serviceStart(service); + } +} -- cgit 1.4.1