aboutsummaryrefslogtreecommitdiff
path: root/initd
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-05-13 16:55:30 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2020-05-13 16:58:15 +0200
commitdd0007f9dcb850806cb62ecc705c35789e12f175 (patch)
treef74be0fb7e5a0d63e1e3f2c88eeb4906bf6d5759 /initd
parent319b20e6c303a5c66513708372af24bcdcd1e905 (diff)
Fix runsvc waiting behaviour if run as subreaper
It basically needs to wait for ALL children (even those created by child processes) to terminate before terminating itself. This commit replaces the waitpid loop with a regular wait that and adds another wait loop at the end of run_sequentially to wait for any transitive children. The sigchld handling is removed from the signal handler and the handler is only installed for SIGINT, SIGTERM and SIGHUP. The other signals that initd hooks are set to default. Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
Diffstat (limited to 'initd')
-rw-r--r--initd/runsvc.c44
1 files changed, 21 insertions, 23 deletions
diff --git a/initd/runsvc.c b/initd/runsvc.c
index 430f2e7..8aaa502 100644
--- a/initd/runsvc.c
+++ b/initd/runsvc.c
@@ -134,6 +134,12 @@ static __attribute__((noreturn)) void argv_exec(exec_t *e)
static pid_t current_child;
+static void runsvc_sighandler(int signo)
+{
+ if (current_child != -1)
+ kill(current_child, signo);
+}
+
static int run_sequentially(exec_t *list, bool direct_exec_last)
{
pid_t ret, pid;
@@ -158,7 +164,7 @@ static int run_sequentially(exec_t *list, bool direct_exec_last)
current_child = pid;
do {
- ret = waitpid(pid, &status, 0);
+ ret = wait(&status);
} while (ret != pid);
current_child = -1;
@@ -170,31 +176,19 @@ static int run_sequentially(exec_t *list, bool direct_exec_last)
return WEXITSTATUS(status);
}
- return EXIT_SUCCESS;
-}
-
-static void runsvc_sighandler(int signo)
-{
- pid_t pid;
+ do {
+ ret = wait(&status);
+ } while (ret != -1 || errno != ECHILD);
- switch (signo) {
- case SIGCHLD:
- while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
- ;
- break;
- default:
- if (current_child != -1)
- kill(current_child, signo);
- break;
- }
+ return ret;
}
pid_t runsvc(service_t *svc)
{
struct sigaction act;
sigset_t mask;
- int i, ret;
pid_t pid;
+ int ret;
pid = fork();
@@ -205,11 +199,15 @@ pid_t runsvc(service_t *svc)
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
- for (i = 1; i < 32; ++i) {
- memset(&act, 0, sizeof(act));
- act.sa_handler = runsvc_sighandler;
- sigaction(i, &act, NULL);
- }
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = runsvc_sighandler;
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+
+ act.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
if (setup_env())
exit(EXIT_FAILURE);