From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This consolidates the handling of signalfd in similar ways as ELL does. --- src/shared/mainloop-glib.c | 1 + src/shared/mainloop-notify.c | 85 ++++++++++++++++++++++++++++++++++++ src/shared/mainloop.h | 1 + 3 files changed, 87 insertions(+) diff --git a/src/shared/mainloop-glib.c b/src/shared/mainloop-glib.c index 42abfddf8..e44197315 100644 --- a/src/shared/mainloop-glib.c +++ b/src/shared/mainloop-glib.c @@ -37,6 +37,7 @@ #include "mainloop.h" #include "mainloop-notify.h" +#include "io.h" static GMainLoop *main_loop; static int exit_status; diff --git a/src/shared/mainloop-notify.c b/src/shared/mainloop-notify.c index 2e3b08f06..17bf2c027 100644 --- a/src/shared/mainloop-notify.c +++ b/src/shared/mainloop-notify.c @@ -31,13 +31,17 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> +#include <signal.h> +#include <sys/signalfd.h> #include <sys/socket.h> #include <sys/un.h> #include "mainloop.h" #include "mainloop-notify.h" #include "timeout.h" +#include "util.h" +#include "io.h" #define WATCHDOG_TRIGGER_FREQ 2 @@ -45,6 +49,14 @@ static int notify_fd = -1; static unsigned int watchdog; +struct signal_data { + struct io *io; + mainloop_signal_func func; + void *user_data; +}; + +static struct signal_data *signal_data; + static bool watchdog_callback(void *user_data) { mainloop_sd_notify("WATCHDOG=1"); @@ -119,3 +131,76 @@ int mainloop_sd_notify(const char *state) return err; } + +static bool signal_read(struct io *io, void *user_data) +{ + struct signal_data *data = user_data; + struct signalfd_siginfo si; + ssize_t result; + int fd; + + fd = io_get_fd(io); + + result = read(fd, &si, sizeof(si)); + if (result != sizeof(si)) + return false; + + if (data && data->func) + data->func(si.ssi_signo, data->user_data); + + return true; +} + +static struct io *setup_signalfd(void *user_data) +{ + struct io *io; + sigset_t mask; + int fd; + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGUSR2); + sigaddset(&mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) + return NULL; + + fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); + if (fd < 0) + return NULL; + + io = io_new(fd); + + io_set_close_on_destroy(io, true); + io_set_read_handler(io, signal_read, user_data, free); + + return io; +} + +int mainloop_run_with_signal(mainloop_signal_func func, void *user_data) +{ + struct signal_data *data; + struct io *io; + int ret; + + if (!func) + return -EINVAL; + + data = new0(struct signal_data, 1); + data->func = func; + data->user_data = user_data; + + io = setup_signalfd(data); + if (!io) { + free(data); + return -errno; + } + + ret = mainloop_run(); + + io_destroy(io); + free(signal_data); + + return ret; +} diff --git a/src/shared/mainloop.h b/src/shared/mainloop.h index 73ed81187..1ede62797 100644 --- a/src/shared/mainloop.h +++ b/src/shared/mainloop.h @@ -36,6 +36,7 @@ void mainloop_quit(void); void mainloop_exit_success(void); void mainloop_exit_failure(void); int mainloop_run(void); +int mainloop_run_with_signal(mainloop_signal_func func, void *user_data); int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback, void *user_data, mainloop_destroy_func destroy); -- 2.17.2