From fcb0e6cc86da076def79c75d7ac3522ac775ccaa Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Thu, 6 Jan 2022 17:25:41 +0100 Subject: extract timedwait --- rvnit.c | 77 ++++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/rvnit.c b/rvnit.c index b5b798d..5d04251 100644 --- a/rvnit.c +++ b/rvnit.c @@ -323,6 +323,40 @@ reap(pid_t pid, int status) return -1; } +pid_t +timedwait(int *wstatus, int secs) +{ + struct timespec timeout = {secs, 0}; + sigset_t childset; + sigemptyset(&childset); + sigaddset(&childset, SIGCHLD); + + sigprocmask(SIG_BLOCK, &childset, 0); + + pid_t pid; + + while (1) { + pid = waitpid(-1, wstatus, WNOHANG); + if (pid == 0) { // nothing to reap + if (sigtimedwait(&childset, 0, &timeout) == SIGCHLD) + continue; + if (errno == EAGAIN) // hit timeout, return pid = 0 + break; + } else if (pid < 0) { + if (errno == ECHILD) + break; + if (errno == EINTR) + continue; + } else { + break; // pid > 0 + } + } + + sigprocmask(SIG_UNBLOCK, &childset, 0); + + return pid; +} + int main() { @@ -479,14 +513,6 @@ main() LOG("shutting down"); -// sigaction(SIGINT, &(struct sigaction){.sa_handler=SIG_DFL}, 0); - - - struct timespec timeout = {7, 0}; - sigset_t childset; - sigemptyset(&childset); - sigaddset(&childset, SIGCHLD); - for (level = 99; level >= 0; level--) { /* kill all of level */ int oneshot = 0; @@ -544,27 +570,26 @@ main() if (!daemons) continue; - sigprocmask(SIG_BLOCK, &childset, 0); + int slayed = 0; while (daemons) { int status = 0; - int pid = waitpid(-1, &status, WNOHANG); - if (pid == 0) { // nothing to reap - if (sigtimedwait(&childset, 0, &timeout) == SIGCHLD) - continue; - if (errno == EAGAIN) { // hit timeout - printf("need kill\n"); - for (i = 0; i < MAX_SV; i++) { - if (services[i].level != level) - continue; - if (services[i].name[2] == 'D' && - services[i].pid > 0) - kill(services[i].pid, SIGKILL); + int pid = timedwait(&status, 7); + if (pid == 0) { // hit timeout + if (slayed) + break; + LOG("slaying level=%d", level); + for (i = 0; i < MAX_SV; i++) { + if (services[i].level != level) + continue; + if (services[i].name[2] == 'D' && + services[i].pid > 0) { + kill(services[i].pid, SIGKILL); + kill(services[i].pid, SIGCONT); } - // XXX ensure this is only run once, - // then force next level - continue; } + slayed = 1; + continue; } if (pid < 0 && errno == ECHILD) @@ -589,7 +614,9 @@ main() } } - sigprocmask(SIG_UNBLOCK, &childset, 0); + if (daemons) { + LOG("slaying unsuccessful, %d daemons left in level=%d, continuing...", daemons, level); + } } dprintf(selflogfd[1], "shutdown\n"); -- cgit 1.4.1