From: Mike Yuan Date: Sat, 6 Jul 2024 17:05:57 +0000 (+0200) Subject: logind-user: take gc_mode into account when reporting user state X-Git-Tag: v257-rc1~914 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=56f4ab290643547853276fb72b4e6960586c3e7c;p=thirdparty%2Fsystemd.git logind-user: take gc_mode into account when reporting user state Prompted by #33650 Previously, if a user manually starts user@.service (which is something we support), we'd track it as 'manager' session. However, since user_get_state() ignores all non-pinning sessions, if lingering is not enabled, the user state would always be reported as 'closing', which is spurious. Let's instead take gc_mode into consideration, and ignore non-pinning sessions only if USER_GC_BY_PIN. --- diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 8066b3e3201..276d5b86f58 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -821,30 +821,30 @@ UserState user_get_state(User *u) { if (!u->started || u->runtime_dir_job) return USER_OPENING; - bool any = false, all_closing = true; + /* USER_GC_BY_PIN: Only pinning sessions count. None -> closing + * USER_GC_BY_ANY: 'manager' sessions also count. However, if lingering is enabled, 'lingering' state + * shall be preferred. 'online' if the manager is manually started by user. */ + + bool has_pinning = false, all_closing = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { - SessionState state; + bool pinned = SESSION_CLASS_PIN_USER(i->class); - /* Ignore sessions that don't pin the user, i.e. are not supposed to have an effect on user state */ - if (!SESSION_CLASS_PIN_USER(i->class)) + if (u->gc_mode == USER_GC_BY_PIN && !pinned) continue; - state = session_get_state(i); - if (state == SESSION_ACTIVE) + has_pinning = has_pinning || pinned; + + SessionState state = session_get_state(i); + if (state == SESSION_ACTIVE && pinned) return USER_ACTIVE; if (state != SESSION_CLOSING) all_closing = false; - - any = true; } - if (any) - return all_closing ? USER_CLOSING : USER_ONLINE; - - if (user_check_linger_file(u) > 0 && user_unit_active(u)) + if (!has_pinning && user_check_linger_file(u) > 0 && user_unit_active(u)) return USER_LINGERING; - return USER_CLOSING; + return all_closing ? USER_CLOSING : USER_ONLINE; } int user_kill(User *u, int signo) {