698723
From 4703c08fe3a8bfa1bc9b893e8bde365b1cbeffd9 Mon Sep 17 00:00:00 2001
698723
From: Lennart Poettering <lennart@poettering.net>
698723
Date: Mon, 6 Aug 2018 18:14:11 +0200
698723
Subject: [PATCH] logind: save/restore User object's "stopping" field during
698723
 restarts
698723
698723
Whether we are stopping or not is highly relevant, hence don't forget it
698723
across restarts.
698723
698723
(cherry picked from commit d865bc024bf28c17120d7322a81e9a99997a59f6)
698723
698723
Related: #1642460
698723
---
698723
 src/login/logind-user.c | 20 +++++++++++++++-----
698723
 src/login/logind-user.h |  5 +++--
698723
 2 files changed, 18 insertions(+), 7 deletions(-)
698723
698723
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
698723
index 17ed361411..35b2ca5489 100644
698723
--- a/src/login/logind-user.c
698723
+++ b/src/login/logind-user.c
698723
@@ -136,9 +136,11 @@ static int user_save_internal(User *u) {
698723
         fprintf(f,
698723
                 "# This is private data. Do not parse.\n"
698723
                 "NAME=%s\n"
698723
-                "STATE=%s\n",
698723
+                "STATE=%s\n"         /* friendly user-facing state */
698723
+                "STOPPING=%s\n",     /* low-level state */
698723
                 u->name,
698723
-                user_state_to_string(user_get_state(u)));
698723
+                user_state_to_string(user_get_state(u)),
698723
+                yes_no(u->stopping));
698723
 
698723
         /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
698723
         if (u->runtime_path)
698723
@@ -277,14 +279,14 @@ int user_save(User *u) {
698723
 }
698723
 
698723
 int user_load(User *u) {
698723
-        _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
698723
+        _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL;
698723
         int r;
698723
 
698723
         assert(u);
698723
 
698723
         r = parse_env_file(NULL, u->state_file, NEWLINE,
698723
                            "SERVICE_JOB", &u->service_job,
698723
-                           "SLICE_JOB",   &u->slice_job,
698723
+                           "STOPPING",    &stopping,
698723
                            "REALTIME",    &realtime,
698723
                            "MONOTONIC",   &monotonic,
698723
                            NULL);
698723
@@ -293,12 +295,20 @@ int user_load(User *u) {
698723
         if (r < 0)
698723
                 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
698723
 
698723
+        if (stopping) {
698723
+                r = parse_boolean(stopping);
698723
+                if (r < 0)
698723
+                        log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping);
698723
+                else
698723
+                        u->stopping = r;
698723
+        }
698723
+
698723
         if (realtime)
698723
                 timestamp_deserialize(realtime, &u->timestamp.realtime);
698723
         if (monotonic)
698723
                 timestamp_deserialize(monotonic, &u->timestamp.monotonic);
698723
 
698723
-        return r;
698723
+        return 0;
698723
 }
698723
 
698723
 static int user_start_service(User *u) {
698723
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
698723
index eba2325284..03e020b870 100644
698723
--- a/src/login/logind-user.h
698723
+++ b/src/login/logind-user.h
698723
@@ -36,8 +36,9 @@ struct User {
698723
         dual_timestamp timestamp;
698723
 
698723
         bool in_gc_queue:1;
698723
-        bool started:1;
698723
-        bool stopping:1;
698723
+
698723
+        bool started:1;       /* Whenever the user being started, has been started or is being stopped again. */
698723
+        bool stopping:1;      /* Whenever the user is being stopped or has been stopped. */
698723
 
698723
         LIST_HEAD(Session, sessions);
698723
         LIST_FIELDS(User, gc_queue);