aboutsummaryrefslogtreecommitdiff
path: root/initd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'initd/main.c')
-rw-r--r--initd/main.c65
1 files changed, 52 insertions, 13 deletions
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);
}
}