diff options
-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); |