aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-05-14 17:49:44 +0200
committerDavid Oberhollenzer <goliath@infraroot.at>2020-05-14 18:12:03 +0200
commit9606d987722ee5b89bbfae230389d3385a3884b0 (patch)
tree716b63d0cbab18a1061967b731c9d65c494bfbc0
parent5b5fc677b313908b8d1a775cd6af08202841d908 (diff)
Replace standard signal handling in initd with signalfd + epoll
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
-rw-r--r--initd/init.h2
-rw-r--r--initd/main.c65
-rw-r--r--initd/runsvc.c17
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) {