From 1a42ce0920bbfc45d8e1193df02f88c84621d2ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Sep 2020 18:06:59 +0200 Subject: [PATCH] logind: make sure when we are explicitly asked to terminate session/user/seat to use "replace" job mode Otherwise our request will possibly fail if something else is already enqeued, but given this is an explicit user request, let's not allow things to fail. Fixes: #16702 --- src/login/logind-dbus.c | 10 +++++----- src/login/logind-dbus.h | 2 +- src/login/logind-session.c | 2 +- src/login/logind-user.c | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 50fb5b8a85..9f16b7f565 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -4072,13 +4072,13 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, return strdup_job(reply, job); } -int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { +int manager_stop_unit(Manager *manager, const char *unit, const char *job_mode, sd_bus_error *error, char **ret_job) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); assert(unit); - assert(job); + assert(ret_job); r = bus_call_method( manager->bus, @@ -4086,12 +4086,12 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c "StopUnit", error, &reply, - "ss", unit, "fail"); + "ss", unit, job_mode ?: "fail"); if (r < 0) { if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, BUS_ERROR_LOAD_FAILED)) { - *job = NULL; + *ret_job = NULL; sd_bus_error_free(error); return 0; } @@ -4099,7 +4099,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c return r; } - return strdup_job(reply, job); + return strdup_job(reply, ret_job); } int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) { diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h index 7707587545..3e0f3805ef 100644 --- a/src/login/logind-dbus.h +++ b/src/login/logind-dbus.h @@ -25,7 +25,7 @@ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_ int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); -int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +int manager_stop_unit(Manager *manager, const char *unit, const char *job_mode, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index c9873155bb..cbb5549bd8 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -768,7 +768,7 @@ static int session_stop_scope(Session *s, bool force) { (s->user->user_record->kill_processes > 0 || manager_shall_kill(s->manager, s->user->user_record->user_name)))) { - r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job); + r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job); if (r < 0) { if (force) return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r)); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index e62f37d58c..9cb4dce641 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -475,7 +475,7 @@ int user_start(User *u) { return 0; } -static void user_stop_service(User *u) { +static void user_stop_service(User *u, bool force) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -487,7 +487,7 @@ static void user_stop_service(User *u) { u->service_job = mfree(u->service_job); - r = manager_stop_unit(u->manager, u->service, &error, &u->service_job); + r = manager_stop_unit(u->manager, u->service, force ? "replace" : "fail", &error, &u->service_job); if (r < 0) log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); } @@ -518,7 +518,7 @@ int user_stop(User *u, bool force) { r = k; } - user_stop_service(u); + user_stop_service(u, force); u->stopping = true;