aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--initd/runsvc.c38
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);