]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: automatically GC lingering users for who now user@.service (nor slice, not...
authorLennart Poettering <lennart@poettering.net>
Wed, 8 Aug 2018 14:04:40 +0000 (16:04 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 13 Oct 2018 10:59:29 +0000 (12:59 +0200)
This heavily borrows from @intelfx' PR #5546, but watches all three
units that are associated with a user now: the slice, the user@.service
and user-runtime-dir@.service.

The logic and reasoning behind it is the same though: there's no value
in keeping lingering users around if all their three services are gone.

Replaces: #5546
Fixes: #4162
src/login/logind-user.c

index 230c8f392d5485ded4186127b9a734c6dfa1b915..16a83ae5d5432746c5f19b1a8cfa21c948d08c3b 100644 (file)
@@ -26,6 +26,7 @@
 #include "special.h"
 #include "stdio-util.h"
 #include "string-table.h"
+#include "strv.h"
 #include "unit-name.h"
 #include "user-util.h"
 #include "util.h"
@@ -540,6 +541,27 @@ int user_check_linger_file(User *u) {
         return true;
 }
 
+static bool user_unit_active(User *u) {
+        const char *i;
+        int r;
+
+        assert(u->service);
+        assert(u->runtime_dir_service);
+        assert(u->slice);
+
+        FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                r = manager_unit_is_active(u->manager, i, &error);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", u->service, bus_error_message(&error, r));
+                if (r != 0)
+                        return true;
+        }
+
+        return false;
+}
+
 bool user_may_gc(User *u, bool drop_not_started) {
         int r;
 
@@ -561,8 +583,10 @@ bool user_may_gc(User *u, bool drop_not_started) {
                         return false; /* Leave it around for a bit longer. */
         }
 
-        /* Is this a user that shall stay around forever? */
-        if (user_check_linger_file(u) > 0)
+        /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check
+         * if any of the three units that we maintain for this user is still around. If none of them is,
+         * there's no need to keep this user around even if lingering is enabled. */
+        if (user_check_linger_file(u) > 0 && user_unit_active(u))
                 return false;
 
         /* Check if our job is still pending */
@@ -619,7 +643,7 @@ UserState user_get_state(User *u) {
                 return all_closing ? USER_CLOSING : USER_ONLINE;
         }
 
-        if (user_check_linger_file(u) > 0)
+        if (user_check_linger_file(u) > 0 && user_unit_active(u))
                 return USER_LINGERING;
 
         return USER_CLOSING;