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);
}
} 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);
}
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;
// 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);
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);
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.
*/