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 | 81 ++++++++++++++++++++++++++++++++++++ src/shared/mainloop.h | 1 + 3 files changed, 83 insertions(+) diff --git a/src/shared/mainloop-glib.c b/src/shared/mainloop-glib.c index 4403d02d8..a83c35482 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 49ca4f6c9..81a2cef28 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 @@ -46,6 +50,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"); @@ -129,3 +141,72 @@ int mainloop_sd_notify(const char *state) return sendmsg(notify_fd, &msghdr, MSG_NOSIGNAL); } + +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) +{ + 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, NULL, NULL); + + return io; +} + +int mainloop_run_with_signal(mainloop_signal_func func, void *user_data) +{ + struct io *io; + int ret; + + if (!func) + return -EINVAL; + + io = setup_signalfd(); + if (!io) + return -errno; + + signal_data = new0(struct signal_data, 1); + signal_data->io = io; + + 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