aboutsummaryrefslogtreecommitdiff
path: root/initd
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-05-09 15:47:15 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2020-05-09 16:00:08 +0200
commit319b20e6c303a5c66513708372af24bcdcd1e905 (patch)
treeb495d7e59fc24948ee95b3428a336604987b23f5 /initd
parent86b9683ec5bc70c875cc0dfc87dbbd61c02682ea (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.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);