From 5b5fc677b313908b8d1a775cd6af08202841d908 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 14 May 2020 16:31:49 +0200 Subject: Move handling of dead children back to SIGCHLD handler Signed-off-by: David Oberhollenzer --- initd/config.c | 20 ++++++-------------- initd/init.h | 3 --- initd/main.c | 52 ++++++++++++++++++++++------------------------------ initd/runsvc.c | 1 + 4 files changed, 29 insertions(+), 47 deletions(-) diff --git a/initd/config.c b/initd/config.c index fa12ab2..3a4eac2 100644 --- a/initd/config.c +++ b/initd/config.c @@ -69,18 +69,6 @@ void config_set_waiting(svc_run_data_t *rt) waiting = rt; } -bool config_is_waiting(void) -{ - if (waiting != NULL) { - if (waiting->state == STATE_RUNNING) - return true; - - waiting = NULL; - } - - return false; -} - svc_run_data_t *config_rt_data_by_pid(pid_t pid) { size_t i; @@ -98,8 +86,12 @@ svc_run_data_t *config_rt_data_by_pid(pid_t pid) svc_run_data_t *config_dequeue(void) { - if (config_is_waiting()) - return NULL; + if (waiting != NULL) { + if (waiting->state == STATE_RUNNING) + return NULL; + + waiting = NULL; + } if (queue_idx >= queue_count[target]) return NULL; diff --git a/initd/init.h b/initd/init.h index 61101c7..5618ccd 100644 --- a/initd/init.h +++ b/initd/init.h @@ -64,9 +64,6 @@ bool config_should_respawn(void); /* refuse to dequeue further services until this one terminates */ void config_set_waiting(svc_run_data_t *rt); -/* are we currently waiting for a service to terminate? */ -bool config_is_waiting(void); - /********** print_status.c **********/ void print_status(const svc_run_data_t *rt); diff --git a/initd/main.c b/initd/main.c index 6485842..d92a823 100644 --- a/initd/main.c +++ b/initd/main.c @@ -22,31 +22,6 @@ fail: return; } -static svc_run_data_t *wait_for_process(void) -{ - svc_run_data_t *rt; - int status; - pid_t pid; - - do { - pid = wait(&status); - - if (pid == -1) { - if (errno == EINTR) - return NULL; - - if (errno == ECHILD) - exit(EXIT_FAILURE); - } - - rt = config_rt_data_by_pid(pid); - } while (rt == NULL); - - rt->status = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; - rt->pid = -1; - return rt; -} - static void handle_exited(svc_run_data_t *rt) { if (rt->svc->type == SVC_RESPAWN) { @@ -85,6 +60,10 @@ static void start_service(svc_run_data_t *rt) static void handle_signal(int signo) { + svc_run_data_t *rt; + int status; + pid_t pid; + switch (signo) { case SIGTERM: config_set_target(TGT_SHUTDOWN); @@ -92,6 +71,22 @@ static void handle_signal(int signo) case SIGINT: config_set_target(TGT_REBOOT); break; + case SIGCHLD: + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + rt = config_rt_data_by_pid(pid); + if (rt == NULL) + continue; + + if (WIFEXITED(status)) { + rt->status = WEXITSTATUS(status); + } else { + rt->status = EXIT_FAILURE; + } + + rt->pid = -1; + handle_exited(rt); + } + break; case SIGHUP: break; case SIGUSR1: @@ -114,6 +109,7 @@ int main(void) sigaction(SIGINT, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGUSR1, &act, NULL); + sigaction(SIGCHLD, &act, NULL); if (reboot(LINUX_REBOOT_CMD_CAD_OFF)) perror("cannot disable CTRL+ALT+DEL"); @@ -122,11 +118,7 @@ int main(void) rt = config_dequeue(); if (rt == NULL) { - rt = wait_for_process(); - if (rt == NULL) - continue; - - handle_exited(rt); + pause(); } else { start_service(rt); } diff --git a/initd/runsvc.c b/initd/runsvc.c index df5a656..5495f15 100644 --- a/initd/runsvc.c +++ b/initd/runsvc.c @@ -205,6 +205,7 @@ pid_t runsvc(service_t *svc) act.sa_handler = SIG_DFL; sigaction(SIGUSR1, &act, NULL); + sigaction(SIGCHLD, &act, NULL); if (setup_env()) exit(EXIT_FAILURE); -- cgit v1.2.3