diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 9c7ad1507b..2e7eb343f1 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -3130,7 +3130,7 @@ int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo "ssi", unit, who == KILL_LEADER ? "main" : "all", signo); } -int manager_unit_is_active(Manager *manager, const char *unit) { +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; @@ -3166,17 +3166,18 @@ int manager_unit_is_active(Manager *manager, const char *unit) { sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) return false; + sd_bus_error_move(ret_error, &error); return r; } r = sd_bus_message_read(reply, "s", &state); if (r < 0) - return -EINVAL; + return r; - return !streq(state, "inactive") && !streq(state, "failed"); + return !STR_IN_SET(state, "inactive", "failed"); } -int manager_job_is_active(Manager *manager, const char *path) { +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; @@ -3201,6 +3202,7 @@ int manager_job_is_active(Manager *manager, const char *path) { if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) return false; + sd_bus_error_move(ret_error, &error); return r; } diff --git a/src/login/logind-session.c b/src/login/logind-session.c index b2a496279b..67790f30f9 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -1008,6 +1008,8 @@ static void session_remove_fifo(Session *s) { } bool session_may_gc(Session *s, bool drop_not_started) { + int r; + assert(s); if (drop_not_started && !s->started) @@ -1021,11 +1023,25 @@ bool session_may_gc(Session *s, bool drop_not_started) { return false; } - if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) - return false; + if (s->scope_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - if (s->scope && manager_unit_is_active(s->manager, s->scope)) - return false; + r = manager_job_is_active(s->manager, s->scope_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + if (s->scope) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_unit_is_active(s->manager, s->scope, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r)); + if (r != 0) + return false; + } return true; } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 416a2b3aae..38a45da1dd 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -534,6 +534,8 @@ int user_check_linger_file(User *u) { } bool user_may_gc(User *u, bool drop_not_started) { + int r; + assert(u); if (drop_not_started && !u->started) @@ -545,11 +547,19 @@ bool user_may_gc(User *u, bool drop_not_started) { if (user_check_linger_file(u) > 0) return false; - if (u->slice_job && manager_job_is_active(u->manager, u->slice_job)) - return false; + /* Check if our job is still pending */ + if (u->service_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - if (u->service_job && manager_job_is_active(u->manager, u->service_job)) - return false; + r = manager_job_is_active(u->manager, u->service_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", u->service_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + /* Note that we don't care if the three units we manage for each user object are up or not, as we are managing + * their state rather than tracking it. */ return true; } diff --git a/src/login/logind.h b/src/login/logind.h index e25bc1e13f..67d12c8b1d 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -166,8 +166,8 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, int manager_stop_unit(Manager *manager, const char *unit, 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); -int manager_job_is_active(Manager *manager, const char *path); +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error); /* gperf lookup function */ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length);