diff --git a/src/shared/mainloop-glib.c b/src/shared/mainloop-glib.c
index 42abfdd..e441973 100644
--- a/src/shared/mainloop-glib.c
+++ b/src/shared/mainloop-glib.c
#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 2e3b08f..17bf2c0 100644
--- a/src/shared/mainloop-notify.c
+++ b/src/shared/mainloop-notify.c
#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
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");
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 73ed811..1ede627 100644
--- a/src/shared/mainloop.h
+++ b/src/shared/mainloop.h
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);