aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-05-14 16:31:49 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2020-05-14 18:12:03 +0200
commit5b5fc677b313908b8d1a775cd6af08202841d908 (patch)
treecfd217112b9aff0099802b61e9c5641b60979b70
parent79bb09eac54d91bf76268baa50ecebea1ab19708 (diff)
Move handling of dead children back to SIGCHLD handler
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
-rw-r--r--initd/config.c20
-rw-r--r--initd/init.h3
-rw-r--r--initd/main.c52
-rw-r--r--initd/runsvc.c1
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);