diff options
author | David Oberhollenzer <goliath@infraroot.at> | 2020-05-14 17:49:44 +0200 |
---|---|---|
committer | David Oberhollenzer <goliath@infraroot.at> | 2020-05-14 18:12:03 +0200 |
commit | 9606d987722ee5b89bbfae230389d3385a3884b0 (patch) | |
tree | 716b63d0cbab18a1061967b731c9d65c494bfbc0 /initd | |
parent | 5b5fc677b313908b8d1a775cd6af08202841d908 (diff) |
Replace standard signal handling in initd with signalfd + epoll
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
Diffstat (limited to 'initd')
-rw-r--r-- | initd/init.h | 2 | ||||
-rw-r--r-- | initd/main.c | 65 | ||||
-rw-r--r-- | initd/runsvc.c | 17 |
3 files changed, 59 insertions, 25 deletions
diff --git a/initd/init.h b/initd/init.h index 5618ccd..5ac6d22 100644 --- a/initd/init.h +++ b/initd/init.h @@ -16,7 +16,9 @@ #include <poll.h> #include <linux/reboot.h> +#include <sys/signalfd.h> #include <sys/reboot.h> +#include <sys/epoll.h> #include <sys/prctl.h> #include <stdbool.h> #include <signal.h> diff --git a/initd/main.c b/initd/main.c index d92a823..9c4bf78 100644 --- a/initd/main.c +++ b/initd/main.c @@ -58,13 +58,17 @@ static void start_service(svc_run_data_t *rt) print_status(rt); } -static void handle_signal(int signo) +static void handle_signal(int fd) { + struct signalfd_siginfo info; svc_run_data_t *rt; int status; pid_t pid; - switch (signo) { + if (read(fd, &info, sizeof(info)) < (ssize_t)sizeof(info)) + return; + + switch (info.ssi_signo) { case SIGTERM: config_set_target(TGT_SHUTDOWN); break; @@ -96,20 +100,43 @@ static void handle_signal(int signo) int main(void) { + struct epoll_event ev; svc_run_data_t *rt; - struct sigaction act; + int ret, sfd, epfd; + sigset_t sigmask; + + cli(NULL); if (config_load()) return EXIT_FAILURE; - memset(&act, 0, sizeof(act)); - act.sa_handler = handle_signal; + epfd = epoll_create1(EPOLL_CLOEXEC); + if (epfd < 0) { + perror("epoll_create"); + return EXIT_FAILURE; + } - sigaction(SIGTERM, &act, NULL); - sigaction(SIGINT, &act, NULL); - sigaction(SIGHUP, &act, NULL); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGCHLD, &act, NULL); + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGTERM); + sigaddset(&sigmask, SIGINT); + sigaddset(&sigmask, SIGHUP); + sigaddset(&sigmask, SIGUSR1); + sigaddset(&sigmask, SIGCHLD); + + sfd = signalfd(-1, &sigmask, SFD_CLOEXEC); + if (sfd < 0) { + perror("signalfd"); + return EXIT_FAILURE; + } + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.fd = sfd; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev)) { + perror("adding signalfd to epoll"); + return EXIT_FAILURE; + } if (reboot(LINUX_REBOOT_CMD_CAD_OFF)) perror("cannot disable CTRL+ALT+DEL"); @@ -117,10 +144,22 @@ int main(void) for (;;) { rt = config_dequeue(); - if (rt == NULL) { - pause(); - } else { + if (rt != NULL) { start_service(rt); + continue; + } + + ret = epoll_wait(epfd, &ev, 1, -1); + if (ret == 0) + continue; + + if (ret < 0) { + perror("epoll wait"); + return EXIT_FAILURE; + } + + if (ev.data.fd == sfd) { + handle_signal(sfd); } } diff --git a/initd/runsvc.c b/initd/runsvc.c index 5495f15..682f4c6 100644 --- a/initd/runsvc.c +++ b/initd/runsvc.c @@ -195,18 +195,6 @@ pid_t runsvc(service_t *svc) perror("fork"); if (pid == 0) { - cli(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(SIGUSR1, &act, NULL); - sigaction(SIGCHLD, &act, NULL); - if (setup_env()) exit(EXIT_FAILURE); @@ -218,6 +206,11 @@ pid_t runsvc(service_t *svc) exit(EXIT_FAILURE); } + memset(&act, 0, sizeof(act)); + act.sa_handler = runsvc_sighandler; + sigaction(SIGTERM, &act, NULL); + sigaction(SIGINT, &act, NULL); + sigaction(SIGHUP, &act, NULL); sti(NULL); if (svc->flags & SVC_FLAG_SUB_REAPER) { |