]> git.ipfire.org Git - pakfire.git/commitdiff
daemon: Terminate all workers when terminating
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 4 Oct 2024 15:40:29 +0000 (15:40 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 4 Oct 2024 15:40:29 +0000 (15:40 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/daemon.c
src/libpakfire/include/pakfire/util.h
src/libpakfire/include/pakfire/worker.h
src/libpakfire/jail.c
src/libpakfire/worker.c

index 839051d7a5b9d7db398d3a97d20d4b1f13d7e558..30aaf80079020baa8d162284c9b9945bac72c4ca 100644 (file)
@@ -58,12 +58,35 @@ struct pakfire_daemon {
        unsigned int running_workers;
 };
 
+/*
+       Terminates all running workers
+*/
+static int pakfire_daemon_terminate_workers(struct pakfire_daemon* daemon) {
+       int r;
+
+       for (unsigned int i = 0; i < MAX_WORKERS; i++) {
+               // Skip any empty slots
+               if (!daemon->workers[i])
+                       continue;
+
+               // Terminate the worker
+               r = pakfire_worker_terminate(daemon->workers[i], SIGTERM);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
 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");
 
+       // Terminate all workers
+       pakfire_daemon_terminate_workers(daemon);
+
        return sd_event_exit(sd_event_source_get_event(source), 0);
 }
 
index 679a92a30c87007343fa23102a31ab9c08ea35cc..41e8501329b34e184c6f8224eb9fd2558e67e642 100644 (file)
@@ -135,6 +135,10 @@ static inline int clone3(struct clone_args* args, size_t size) {
        return syscall(__NR_clone3, args, size);
 }
 
+static inline int pidfd_send_signal(int pidfd, int sig, siginfo_t* info, unsigned int flags) {
+       return syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags);
+}
+
 #endif
 
 #endif /* PAKFIRE_UTIL_H */
index de0568d86d07108f15ca83da511d30bb65fef81a..213c076857f8d2ffc79dfecea107d9e50dd19ee5 100644 (file)
@@ -36,6 +36,7 @@ struct pakfire_worker* pakfire_worker_unref(struct pakfire_worker* worker);
 
 // Launch
 int pakfire_worker_launch(struct pakfire_worker* worker);
+int pakfire_worker_terminate(struct pakfire_worker* worker, int signal);
 
 int pakfire_worker_exited(sd_event_source* s, const siginfo_t* si, void* data);
 
index 657d25a47ea3dbb0c60ee0cf108b15da032d6af0..a3f4da08a1c3561e6caffeb5d98529e61b3c0601 100644 (file)
@@ -215,10 +215,6 @@ struct pakfire_jail_exec {
        } pty;
 };
 
-static int pidfd_send_signal(int pidfd, int sig, siginfo_t* info, unsigned int flags) {
-       return syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags);
-}
-
 static int pivot_root(const char* new_root, const char* old_root) {
        return syscall(SYS_pivot_root, new_root, old_root);
 }
index 0ec7a954854f3f727d6255bf26ce65854a885bdf..2f86e96efd6a8e5d3b8309012abe51c4a454122e 100644 (file)
@@ -87,6 +87,15 @@ struct pakfire_worker_ctx {
        struct pakfire_xfer* control;
 };
 
+static int __pakfire_worker_terminate(sd_event_source* source,
+               const struct signalfd_siginfo* si, void* data) {
+       struct pakfire_worker* worker = data;
+
+       CTX_DEBUG(worker->ctx, "Received signal to terminate...\n");
+
+       return sd_event_exit(sd_event_source_get_event(source), 0);
+}
+
 static int pakfire_parse_job(struct pakfire_worker* worker, json_object* data) {
        json_object* ccache = NULL;
        json_object* o = NULL;
@@ -335,6 +344,8 @@ int pakfire_worker_create(struct pakfire_worker** worker, struct pakfire_ctx* ct
        // Store a reference to the daemon
        w->daemon = pakfire_daemon_ref(daemon);
 
+       // Initialize the PID file descriptor
+       w->pidfd = -1;
 
        // Parse the job
        r = pakfire_parse_job(w, data);
@@ -390,6 +401,22 @@ static int pakfire_worker_setup_loop(struct pakfire_worker_ctx* ctx) {
                return r;
        }
 
+       // Listen for SIGTERM
+       r = sd_event_add_signal(ctx->loop, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK,
+               __pakfire_worker_terminate, ctx->worker);
+       if (r < 0) {
+               CTX_ERROR(ctx->ctx, "Could not register handling SIGTERM: %s\n", strerror(-r));
+               return r;
+       }
+
+       // Listen for SIGINT
+       r = sd_event_add_signal(ctx->loop, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK,
+               __pakfire_worker_terminate, ctx->worker);
+       if (r < 0) {
+               CTX_ERROR(ctx->ctx, "Could not register handling SIGINT: %s\n", strerror(-r));
+               return r;
+       }
+
        // Setup the reconnection timer
        r = sd_event_add_time_relative(ctx->loop, &ctx->connect_timer,
                CLOCK_MONOTONIC, 0, 0, pakfire_worker_connect, ctx);
@@ -517,6 +544,26 @@ int pakfire_worker_launch(struct pakfire_worker* worker) {
        return pakfire_worker_parent(worker);
 }
 
+/*
+       Terminates the worker (if it is still running)
+*/
+int pakfire_worker_terminate(struct pakfire_worker* worker, int signal) {
+       int r;
+
+       // Fail if we don't have a PID file descriptor
+       if (worker->pidfd < 0)
+               return -ENOTSUP;
+
+       // Send a signal to the child process
+       r = pidfd_send_signal(worker->pidfd, signal, NULL, 0);
+       if (r) {
+               CTX_ERROR(worker->ctx, "Could not terminate worker: %m\n");
+               return r;
+       }
+
+       return 0;
+}
+
 /*
        This method is triggered by SIGCHLD whenever the worker exits.
 */