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