From: Michael Tremer Date: Fri, 4 Oct 2024 15:40:29 +0000 (+0000) Subject: daemon: Terminate all workers when terminating X-Git-Tag: 0.9.30~1176 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78a4450652c0cdfc61a29648cf47b1d90a1abdab;p=pakfire.git daemon: Terminate all workers when terminating Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/daemon.c b/src/libpakfire/daemon.c index 839051d7a..30aaf8007 100644 --- a/src/libpakfire/daemon.c +++ b/src/libpakfire/daemon.c @@ -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); } diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index 679a92a30..41e850132 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -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 */ diff --git a/src/libpakfire/include/pakfire/worker.h b/src/libpakfire/include/pakfire/worker.h index de0568d86..213c07685 100644 --- a/src/libpakfire/include/pakfire/worker.h +++ b/src/libpakfire/include/pakfire/worker.h @@ -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); diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index 657d25a47..a3f4da08a 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -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); } diff --git a/src/libpakfire/worker.c b/src/libpakfire/worker.c index 0ec7a9548..2f86e96ef 100644 --- a/src/libpakfire/worker.c +++ b/src/libpakfire/worker.c @@ -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. */