diff options
author | David Härdeman <david@hardeman.nu> | 2020-06-22 09:00:56 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-06-22 09:00:56 +0200 |
commit | 49ae8b30a8f6ca89114af89b215b655de8ea66f8 (patch) | |
tree | a5e0eb122cf99756488bba5db59199a5ec6cadf1 | |
parent | 94bbdce6b742ab2f62cfa9513e13f27a0f78973b (diff) |
Improve signal handler to mimic signalfd better
-rw-r--r-- | main.c | 136 | ||||
-rw-r--r-- | utils.h | 3 |
2 files changed, 69 insertions, 70 deletions
@@ -11,7 +11,6 @@ #include <stdbool.h> #include <getopt.h> #include <sys/signalfd.h> -#include <sys/eventfd.h> #include <signal.h> #include <systemd/sd-daemon.h> #include <cap-ng.h> @@ -545,10 +544,11 @@ cfg_apply(struct cfg *cfg) } struct signalfd_ev { - struct uring_task task; //struct signalfd_siginfo buf; struct cfg *cfg; - uint64_t buf; + struct uring_task task; + struct uring_task_buf tbuf; + int pipe[2]; }; static void @@ -591,25 +591,63 @@ dump_tree(struct cfg *cfg) debug(DBG_REF, "\n\n"); } -static struct dns_async *hack_dns = NULL; - static void signalfd_read(struct cfg *cfg, struct uring_task *task, int res) { struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task); struct server *server, *stmp; + static unsigned count = 0; + siginfo_t *si; assert_return(cfg && task); assert_task_alive(DBG_SIG, task); - if (res != sizeof(sev->buf)) + si = (siginfo_t *)task->tbuf->buf; + if (res != sizeof(*si)) die("error in signalfd (%i)", res); - if (sev->buf < 1000) { + switch (si->si_signo) { + case SIGUSR1: { + struct dns_async *dns; + + debug(DBG_SIG, "Got a SIGUSR1"); + if (si->si_code != SI_ASYNCNL || !si->si_ptr) { + error("SIGUSR1: unexpected values in siginfo"); + goto out; + } + + dns = si->si_ptr; + if (!dns->cb) { + error("DNS callback not set"); + goto out; + } + + debug(DBG_DNS, "DNS lookup complete, dns: %p, dns->cb: %p", + dns, dns->cb); + dns->cb(dns); + break; + } + + case SIGUSR2: + debug(DBG_SIG, "got a SIGUSR2"); + dump_tree(cfg); + break; + + case SIGTERM: + debug(DBG_SIG, "Got a SIGINT/SIGHUP"); verbose("got a signal to quit"); sd_notifyf(0, "STOPPING=1\nSTATUS=Received signal, exiting"); exit(EXIT_SUCCESS); - } else if (sev->buf < 10000) { + break; + + case SIGINT: + case SIGHUP: + count++; + if (count > 5) { + dump_tree(cfghack); + exit(EXIT_FAILURE); + } + verbose("got a signal to dump tree"); sd_notifyf(0, "STOPPING=1\nSTATUS=Received signal, exiting"); dump_tree(cfg); @@ -622,75 +660,32 @@ signalfd_read(struct cfg *cfg, struct uring_task *task, int res) server_delete(cfg, server); uring_delete(cfg); return; - } else { - debug(DBG_DNS, "DNS lookup complete, dns: %p, dns->cb: %p", - hack_dns, - hack_dns ? hack_dns->cb : NULL); - if (!hack_dns || !hack_dns->cb) { - error("DNS callback not set"); - goto out; - } - - hack_dns->cb(hack_dns); + default: + error("got an unknown signal: %i", si->si_signo); + break; } out: - uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), signalfd_read); + uring_tbuf_read(cfg, &sev->task, signalfd_read); } -static int hack_efd = -1; - static void -hack_handler(int signum, siginfo_t *info, void *ucontext) +hack_signal_handler(int signum, siginfo_t *si, void *ucontext) { - uint64_t val; - static unsigned count = 0; + ssize_t r; - assert_return(signum > 0 && info); + assert_return(signum > 0 && si); - count++; - if (count > 5) { - dump_tree(cfghack); - exit(EXIT_FAILURE); - } + r = write(cfghack->sev->pipe[PIPE_WR], si, sizeof(*si)); + if (r != sizeof(*si)) + error("write: %zi\n", r); - switch (signum) { - case SIGUSR1: - debug(DBG_SIG, "Got a SIGUSR1"); - if (info->si_code != SI_ASYNCNL || info->si_signo != SIGUSR1 || !info->si_ptr) { - debug(DBG_SIG, "unexpected values in siginfo"); - return; - } - debug(DBG_SIG, "SIGUSR1 struct dns_async: %p", info->si_ptr); - hack_dns = info->si_ptr; - val = 10000; - break; - case SIGINT: - debug(DBG_SIG, "Got a SIGINT"); - val = 1000; - break; - case SIGHUP: - debug(DBG_SIG, "Got a SIGHUP"); - val = 1000; - break; - case SIGTERM: - debug(DBG_SIG, "Got a SIGTERM"); - val = 1; - break; - default: - error("Got an unknown sig (%i)", signum); - val = 1; - break; - } - - write(hack_efd, &val, sizeof(val)); } static void signalfd_init(struct cfg *cfg) { - int sfd; //sigset_t mask; struct signalfd_ev *sev; @@ -700,6 +695,9 @@ signalfd_init(struct cfg *cfg) if (!sev) die("malloc: %m"); + if (pipe2(sev->pipe, O_CLOEXEC) < 0) + die("pipe2: %m"); + /* sigfillset(&mask); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) @@ -712,29 +710,27 @@ signalfd_init(struct cfg *cfg) struct sigaction action; sigfillset(&action.sa_mask); - action.sa_sigaction = hack_handler; + action.sa_sigaction = hack_signal_handler; action.sa_flags = SA_SIGINFO; sigaction(SIGINT, &action, NULL); sigaction(SIGHUP, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); action.sa_handler = SIG_IGN; action.sa_flags = 0; sigaction(SIGPIPE, &action, NULL); - sfd = eventfd(0, EFD_CLOEXEC); - if (sfd < 0) - die("eventfd: %m"); - - debug(DBG_SIG, "using fd %i", sfd); + debug(DBG_SIG, "using pipe fds %i -> %i", + sev->pipe[PIPE_WR], sev->pipe[PIPE_RD]); uring_task_init(cfg, &sev->task, "sev", uring_parent(cfg), signalfd_free); - uring_task_set_fd(&sev->task, sfd); + uring_task_set_fd(&sev->task, sev->pipe[PIPE_RD]); + uring_task_set_buf(&sev->task, &sev->tbuf); cfg->sev = sev; sev->cfg = cfg; - hack_efd = sfd; - uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), signalfd_read); + uring_tbuf_read(cfg, &sev->task, signalfd_read); } int @@ -152,6 +152,9 @@ static inline bool list_empty(struct list_head *list) return list->next == list; } +#define PIPE_RD 0 +#define PIPE_WR 1 + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |