From: Michael Tremer Date: Mon, 27 Jan 2025 11:29:28 +0000 (+0000) Subject: daemon: Prevent the system from shutting down when jobs are running X-Git-Tag: 0.9.30~358 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a81c1bbbe199ac370738e7903b9b38b91435185;p=pakfire.git daemon: Prevent the system from shutting down when jobs are running Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/daemon.c b/src/pakfire/daemon.c index 78112062..a906fc74 100644 --- a/src/pakfire/daemon.c +++ b/src/pakfire/daemon.c @@ -70,6 +70,7 @@ struct pakfire_daemon { // dbus sd_bus* bus; + int inhibitfd; // Kerberos Authentication struct { @@ -352,6 +353,77 @@ ERROR: return r; } +/* + * Prevents that the system can be shut down when there are jobs running... + */ +static int pakfire_daemon_inhibit_shutdown(struct pakfire_daemon* daemon) { + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message* reply = NULL; + int r; + + // Don't do this again if we are already holding the lock + if (daemon->inhibitfd >= 0) + return 0; + + // Call the Inhibit method + r = sd_bus_call_method( + daemon->bus, + + // Destination, Path & Interface + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + + // Method + "Inhibit", + + // Error + &error, + + // Reply + &reply, + + // Arguments + "ssss", + "shutdown:sleep:idle", + "pakfire-daemon", + "Prevent shutdown while build jobs are running", + "block" + ); + if (r < 0) { + ERROR(daemon->ctx, "Failed to inhibit shutdown: %s\n", error.message); + goto ERROR; + } + + // Read the file descriptor from the reply + r = sd_bus_message_read(reply, "h", &daemon->inhibitfd); + if (r < 0) { + ERROR(daemon->ctx, "Failed to parse response message: %s\n", strerror(-r)); + goto ERROR; + } + + DEBUG(daemon->ctx, "Successfully inhibited shutdown\n"); + +ERROR: + sd_bus_error_free(&error); + if (reply) + sd_bus_message_unref(reply); + + return r; +} + +static int pakfire_daemon_release_inhibit_shutdown(struct pakfire_daemon* daemon) { + // If we don't hold the lock, we cannot release it + if (daemon->inhibitfd >= 0) { + close(daemon->inhibitfd); + daemon->inhibitfd = -EBADF; + + DEBUG(daemon->ctx, "Released shutdown inhibition\n"); + } + + return 0; +} + /* Called when a new job has been received */ @@ -360,11 +432,16 @@ static int pakfire_daemon_job(struct pakfire_daemon* daemon, json_object* m) { struct json_object* data = NULL; int r; + // Inhibit shutdown + r = pakfire_daemon_inhibit_shutdown(daemon); + if (r < 0) + goto ERROR; + // Fetch the data from the message if (!json_object_object_get_ex(m, "data", &data)) { ERROR(daemon->ctx, "Job does not have any data\n"); - - return -EINVAL; + r = -EINVAL; + goto ERROR; } // Create a new job @@ -946,6 +1023,9 @@ ERROR: } static void pakfire_daemon_free(struct pakfire_daemon* daemon) { + // Release shutdown inhibition + pakfire_daemon_release_inhibit_shutdown(daemon); + if (daemon->krb5.principal) krb5_free_principal(daemon->krb5.ctx, daemon->krb5.principal); if (daemon->krb5.ccache) @@ -989,6 +1069,9 @@ int pakfire_daemon_create(struct pakfire_daemon** daemon, struct pakfire_ctx* ct // Initialize the reference counter d->nrefs = 1; + // Initialize file descriptors + d->inhibitfd = -EBADF; + // Read configuration r = pakfire_daemon_configure(d); if (r < 0) @@ -1088,6 +1171,8 @@ ERROR: Called after a job has exited */ int pakfire_daemon_job_finished(struct pakfire_daemon* daemon, struct pakfire_job* job) { + int r; + DEBUG(daemon->ctx, "Removing job %p\n", job); for (unsigned int i = 0; i < MAX_JOBS; i++) { @@ -1104,6 +1189,13 @@ int pakfire_daemon_job_finished(struct pakfire_daemon* daemon, struct pakfire_jo // Now we have one less job running daemon->running_jobs--; + // Release the shutdown inhibition if there are no more jobs running + if (!daemon->running_jobs) { + r = pakfire_daemon_release_inhibit_shutdown(daemon); + if (r < 0) + return r; + } + return 0; }