]> git.ipfire.org Git - pakfire.git/commitdiff
daemon: Use the systemd event loop instead of epoll
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 10 Aug 2024 12:28:39 +0000 (12:28 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 10 Aug 2024 12:28:39 +0000 (12:28 +0000)
This will allow us more flexiblity and already implements a lot of
features.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/daemon.c

index 934ba2704b85b98e85c825b4f98b2f31ad8bd537..9fd9cc5af69b3b4c2f0f9d087f818391f25748d4 100644 (file)
@@ -20,7 +20,9 @@
 
 #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>
@@ -34,11 +36,61 @@ struct pakfire_daemon {
 
        // 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);
@@ -59,6 +111,11 @@ int pakfire_daemon_create(struct pakfire_daemon** daemon, struct pakfire_ctx* ct
        // 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)
@@ -91,66 +148,27 @@ struct pakfire_daemon* pakfire_daemon_unref(struct pakfire_daemon* daemon) {
 }
 
 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) {