b12df0
From 0314e68fe961cec941b1b0eb1cbcca4546cfdfdb Mon Sep 17 00:00:00 2001
b12df0
From: Lennart Poettering <lennart@poettering.net>
b12df0
Date: Fri, 3 Aug 2018 19:04:35 +0200
b12df0
Subject: [PATCH] logind: fix serialization/deserialization of user's "display
b12df0
 session"
b12df0
b12df0
Previously this was serialized as part of the user object. This didn't
b12df0
work however, as we load users first, and sessions seconds and hence
b12df0
referencing a session from the user load logic cannot work.
b12df0
b12df0
Fix this by storing an IS_DISPLAY property along with each session, and
b12df0
make the session with this set display session when it is loaded.
b12df0
b12df0
(cherry picked from commit 1c8280fd47b6561d35b15b3b6d49bdeacf891bfd)
b12df0
b12df0
Related: #1642460
b12df0
---
b12df0
 src/login/logind-session.c | 18 +++++++++++++++++-
b12df0
 src/login/logind-user.c    | 18 ++++--------------
b12df0
 2 files changed, 21 insertions(+), 15 deletions(-)
b12df0
b12df0
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
b12df0
index 5621d59a41..0afb065b2b 100644
b12df0
--- a/src/login/logind-session.c
b12df0
+++ b/src/login/logind-session.c
b12df0
@@ -184,11 +184,13 @@ int session_save(Session *s) {
b12df0
                 "UID="UID_FMT"\n"
b12df0
                 "USER=%s\n"
b12df0
                 "ACTIVE=%i\n"
b12df0
+                "IS_DISPLAY=%i\n"
b12df0
                 "STATE=%s\n"
b12df0
                 "REMOTE=%i\n",
b12df0
                 s->user->uid,
b12df0
                 s->user->name,
b12df0
                 session_is_active(s),
b12df0
+                s->user->display == s,
b12df0
                 session_state_to_string(session_get_state(s)),
b12df0
                 s->remote);
b12df0
 
b12df0
@@ -359,7 +361,8 @@ int session_load(Session *s) {
b12df0
                 *monotonic = NULL,
b12df0
                 *controller = NULL,
b12df0
                 *active = NULL,
b12df0
-                *devices = NULL;
b12df0
+                *devices = NULL,
b12df0
+                *is_display = NULL;
b12df0
 
b12df0
         int k, r;
b12df0
 
b12df0
@@ -389,6 +392,7 @@ int session_load(Session *s) {
b12df0
                            "CONTROLLER",     &controller,
b12df0
                            "ACTIVE",         &active,
b12df0
                            "DEVICES",        &devices,
b12df0
+                           "IS_DISPLAY",     &is_display,
b12df0
                            NULL);
b12df0
 
b12df0
         if (r < 0)
b12df0
@@ -496,6 +500,18 @@ int session_load(Session *s) {
b12df0
                         s->was_active = k;
b12df0
         }
b12df0
 
b12df0
+        if (is_display) {
b12df0
+                /* Note that when enumerating users are loaded before sessions, hence the display session to use is
b12df0
+                 * something we have to store along with the session and not the user, as in that case we couldn't
b12df0
+                 * apply it at the time we load the user. */
b12df0
+
b12df0
+                k = parse_boolean(is_display);
b12df0
+                if (k < 0)
b12df0
+                        log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
b12df0
+                else if (k > 0)
b12df0
+                        s->user->display = s;
b12df0
+        }
b12df0
+
b12df0
         if (controller) {
b12df0
                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
b12df0
                         session_set_controller(s, controller, false, false);
b12df0
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
b12df0
index 60ccd62abb..17ed361411 100644
b12df0
--- a/src/login/logind-user.c
b12df0
+++ b/src/login/logind-user.c
b12df0
@@ -277,8 +277,7 @@ int user_save(User *u) {
b12df0
 }
b12df0
 
b12df0
 int user_load(User *u) {
b12df0
-        _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
b12df0
-        Session *s = NULL;
b12df0
+        _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
b12df0
         int r;
b12df0
 
b12df0
         assert(u);
b12df0
@@ -286,22 +285,13 @@ int user_load(User *u) {
b12df0
         r = parse_env_file(NULL, u->state_file, NEWLINE,
b12df0
                            "SERVICE_JOB", &u->service_job,
b12df0
                            "SLICE_JOB",   &u->slice_job,
b12df0
-                           "DISPLAY",     &display,
b12df0
                            "REALTIME",    &realtime,
b12df0
                            "MONOTONIC",   &monotonic,
b12df0
                            NULL);
b12df0
-        if (r < 0) {
b12df0
-                if (r == -ENOENT)
b12df0
-                        return 0;
b12df0
-
b12df0
+        if (r == -ENOENT)
b12df0
+                return 0;
b12df0
+        if (r < 0)
b12df0
                 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
b12df0
-        }
b12df0
-
b12df0
-        if (display)
b12df0
-                s = hashmap_get(u->manager->sessions, display);
b12df0
-
b12df0
-        if (s && s->display && display_is_local(s->display))
b12df0
-                u->display = s;
b12df0
 
b12df0
         if (realtime)
b12df0
                 timestamp_deserialize(realtime, &u->timestamp.realtime);