diff options
author | David Oberhollenzer <goliath@infraroot.at> | 2020-05-13 16:55:30 +0200 |
---|---|---|
committer | David Oberhollenzer <goliath@infraroot.at> | 2020-05-13 16:58:15 +0200 |
commit | dd0007f9dcb850806cb62ecc705c35789e12f175 (patch) | |
tree | f74be0fb7e5a0d63e1e3f2c88eeb4906bf6d5759 | |
parent | 319b20e6c303a5c66513708372af24bcdcd1e905 (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>
-rw-r--r-- | initd/runsvc.c | 44 |
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); |