#include <errno.h>
#include <stdlib.h>
-#include <sys/epoll.h>
+
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-event.h>
#include <pakfire/buildservice.h>
#include <pakfire/ctx.h>
// Pakfire Build Service
struct pakfire_buildservice* service;
+
+ // Event Loop
+ sd_event* loop;
};
+static int pakfire_daemon_terminate(sd_event_source* source,
+ const struct signalfd_siginfo* si, void* data) {
+ struct pakfire_daemon* daemon = data;
+
+ CTX_DEBUG(daemon->ctx, "Received signal to terminate...\n");
+
+ return sd_event_exit(sd_event_source_get_event(source), 0);
+}
+
+static int pakfire_daemon_setup_loop(struct pakfire_daemon* daemon) {
+ int r;
+
+ // Fetch a reference to the default event loop
+ r = sd_event_default(&daemon->loop);
+ if (r < 0) {
+ CTX_ERROR(daemon->ctx, "Could not setup event loop: %s\n", strerror(-r));
+ return 1;
+ }
+
+ // Enable the watchdog
+ r = sd_event_set_watchdog(daemon->loop, 1);
+ if (r < 0) {
+ CTX_ERROR(daemon->ctx, "Could not activate watchdog: %s\n", strerror(-r));
+ return 1;
+ }
+
+ // Listen for SIGTERM
+ r = sd_event_add_signal(daemon->loop, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK,
+ pakfire_daemon_terminate, daemon);
+ if (r < 0) {
+ CTX_ERROR(daemon->ctx, "Could not register handling SIGTERM: %s\n", strerror(-r));
+ return 1;
+ }
+
+ // Listen for SIGINT
+ r = sd_event_add_signal(daemon->loop, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK,
+ pakfire_daemon_terminate, daemon);
+ if (r < 0) {
+ CTX_ERROR(daemon->ctx, "Could not register handling SIGINT: %s\n", strerror(-r));
+ return 1;
+ }
+
+ return 0;
+}
+
static void pakfire_daemon_free(struct pakfire_daemon* daemon) {
if (daemon->service)
pakfire_buildservice_unref(daemon->service);
+ if (daemon->loop)
+ sd_event_unref(daemon->loop);
if (daemon->ctx)
pakfire_ctx_unref(daemon->ctx);
free(daemon);
// Initialize the reference counter
d->nrefs = 1;
+ // Setup the event loop
+ r = pakfire_daemon_setup_loop(d);
+ if (r)
+ goto ERROR;
+
// Connect to the buildservice
r = pakfire_buildservice_create(&d->service, d->ctx);
if (r)
}
static int pakfire_daemon_loop(struct pakfire_daemon* daemon) {
- struct epoll_event events[EPOLL_MAX_EVENTS];
- struct epoll_event event;
- int epollfd = -1;
- int num = 0;
- int fd = -1;
- int e;
int r;
- // Setup epoll()
- epollfd = epoll_create1(EPOLL_CLOEXEC);
- if (epollfd < 0) {
- CTX_ERROR(daemon->ctx, "Could not setup main loop: %s\n", strerror(errno));
- r = -errno;
+ // We are now ready
+ sd_notify(0, "READY=1\n" "STATUS=Ready...");
+
+ // Launch the event loop
+ r = sd_event_loop(daemon->loop);
+ if (r < 0) {
+ CTX_ERROR(daemon->ctx, "Could not run the event loop: %s\n", strerror(-r));
goto ERROR;
}
- CTX_DEBUG(daemon->ctx, "Entering main loop...\n");
-
- // Main loop, loop, loop, looooop....
- for (;;) {
- num = epoll_wait(epollfd, events, EPOLL_MAX_EVENTS, -1);
- if (num < 1) {
- switch (errno) {
- case EINTR:
- break;
-
- default:
- CTX_ERROR(daemon->ctx, "epoll_wait() failed: %m\n");
- r = -errno;
- break;
- }
- goto ERROR;
- }
-
- // Handle all events
- for (int i = 0; i < num; i++) {
- fd = events[i].data.fd;
- e = events[i].events;
-
- // XXX Do the work...
-
- // Remove the file descriptor if it has been closed
- if (e & EPOLLHUP) {
- r = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
- if (r) {
- CTX_ERROR(daemon->ctx, "Could not remove closed fd %d: %s\n", fd, strerror(errno));
- r = -errno;
- goto ERROR;
- }
- }
- }
- }
+ // Let systemd know that we are shutting down
+ sd_notify(0, "STOPPING=1\n" "STATUS=Shutting down...");
-ERROR:
- CTX_DEBUG(daemon->ctx, "Exited main loop...\n");
+ return 0;
- if (epollfd >= 0)
- close(epollfd);
+ERROR:
+ sd_notifyf(0, "ERRNO=%i", -r);
- return r;
+ return 1;
}
int pakfire_daemon_main(struct pakfire_daemon* daemon) {