diff options
author | David Oberhollenzer <goliath@infraroot.at> | 2020-05-09 15:47:15 +0200 |
---|---|---|
committer | David Oberhollenzer <goliath@infraroot.at> | 2020-05-09 16:00:08 +0200 |
commit | 319b20e6c303a5c66513708372af24bcdcd1e905 (patch) | |
tree | b495d7e59fc24948ee95b3428a336604987b23f5 /initd | |
parent | 86b9683ec5bc70c875cc0dfc87dbbd61c02682ea (diff) |
Install a propper signal handler in runsvc
If runsvc is installed as sub reaper, it must handle SIGCHLD or
the system will accumulate zombie processes. Also, forward all
other signal to the currently supervised child process and hope
that if it is SIGTERM, the child itself knows how to shut down
any other processes it created.
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
Diffstat (limited to 'initd')
-rw-r--r-- | initd/runsvc.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/initd/runsvc.c b/initd/runsvc.c index 144490b..430f2e7 100644 --- a/initd/runsvc.c +++ b/initd/runsvc.c @@ -132,11 +132,15 @@ static __attribute__((noreturn)) void argv_exec(exec_t *e) exit(EXIT_FAILURE); } +static pid_t current_child; + static int run_sequentially(exec_t *list, bool direct_exec_last) { pid_t ret, pid; int status; + current_child = -1; + for (; list != NULL; list = list->next) { if (list->next == NULL && direct_exec_last) argv_exec(list); @@ -151,10 +155,14 @@ static int run_sequentially(exec_t *list, bool direct_exec_last) return EXIT_FAILURE; } + current_child = pid; + do { ret = waitpid(pid, &status, 0); } while (ret != pid); + current_child = -1; + if (!WIFEXITED(status)) return EXIT_FAILURE; @@ -165,11 +173,28 @@ static int run_sequentially(exec_t *list, bool direct_exec_last) return EXIT_SUCCESS; } +static void runsvc_sighandler(int signo) +{ + pid_t pid; + + switch (signo) { + case SIGCHLD: + while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) + ; + break; + default: + if (current_child != -1) + kill(current_child, signo); + break; + } +} + pid_t runsvc(service_t *svc) { + struct sigaction act; sigset_t mask; + int i, ret; pid_t pid; - int ret; pid = fork(); @@ -177,9 +202,15 @@ pid_t runsvc(service_t *svc) perror("fork"); if (pid == 0) { - sigemptyset(&mask); + 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); + } + if (setup_env()) exit(EXIT_FAILURE); @@ -191,6 +222,9 @@ pid_t runsvc(service_t *svc) exit(EXIT_FAILURE); } + sigemptyset(&mask); + sigprocmask(SIG_SETMASK, &mask, NULL); + if (svc->flags & SVC_FLAG_SUB_REAPER) { prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); |