dcavalca / rpms / systemd

Forked from rpms/systemd 2 years ago
Clone
Zbigniew Jędrzejewski-Szmek 4f9456
From 634acdc887a967039233e40b96e4f6ff79f86b72 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 4f9456
From: Michal Sekletar <msekleta@redhat.com>
Zbigniew Jędrzejewski-Szmek 4f9456
Date: Mon, 3 Mar 2014 15:37:49 +0100
Zbigniew Jędrzejewski-Szmek 4f9456
Subject: [PATCH] logind: rework session shutdown logic
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
Simplify the shutdown logic a bit:
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
- Keep the session FIFO around in the PAM module, even after the session
Zbigniew Jędrzejewski-Szmek 4f9456
  shutdown hook has been finished. This allows logind to track precisely
Zbigniew Jędrzejewski-Szmek 4f9456
  when the PAM handler goes away.
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
- In the ReleaseSession() call start a timer, that will stop terminate
Zbigniew Jędrzejewski-Szmek 4f9456
  the session when elapsed.
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
- Never fiddle with the KillMode of scopes to configure whether user
Zbigniew Jędrzejewski-Szmek 4f9456
  processes should be killed or not. Instead, simply leave the scope
Zbigniew Jędrzejewski-Szmek 4f9456
  units around when we terminate a session whose processes should not be
Zbigniew Jędrzejewski-Szmek 4f9456
  killed.
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
- When killing is enabled, stop the session scope on FIFO EOF or after
Zbigniew Jędrzejewski-Szmek 4f9456
  the ReleaseSession() timeout. When killing is disabled, simply tell
Zbigniew Jędrzejewski-Szmek 4f9456
  PID 1 to abandon the scope.
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
Because the scopes stay around and hence all processes are always member
Zbigniew Jędrzejewski-Szmek 4f9456
of a scope, the system shutdown logic should be more robust, as the
Zbigniew Jędrzejewski-Szmek 4f9456
scopes can be shutdown as part of the usual shutdown logic.
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
Based-on: 5f41d1f10fd97e93517b6a762b1bec247f4d1171
Zbigniew Jędrzejewski-Szmek 4f9456
---
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind-dbus.c    |  51 +++++++++++-------
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind-session.c | 130 +++++++++++++++++++++++++++++++++++----------
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind-session.h |   4 ++
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind-user.c    |  23 +++++---
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind-user.h    |   1 +
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind.c         |  23 ++++++--
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/logind.h         |   4 +-
Zbigniew Jędrzejewski-Szmek 4f9456
 src/login/pam-module.c     |  11 ++--
Zbigniew Jędrzejewski-Szmek 4f9456
 8 files changed, 182 insertions(+), 65 deletions(-)
Zbigniew Jędrzejewski-Szmek 4f9456
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index 6f3e442efb..63f0d3c7a3 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind-dbus.c
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind-dbus.c
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -1746,13 +1746,7 @@ static DBusHandlerResult manager_message_handler(
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (!session)
Zbigniew Jędrzejewski-Szmek 4f9456
                         return bus_send_error_reply(connection, message, &error, -ENOENT);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-                /* We use the FIFO to detect stray sessions where the
Zbigniew Jędrzejewski-Szmek 4f9456
-                process invoking PAM dies abnormally. We need to make
Zbigniew Jędrzejewski-Szmek 4f9456
-                sure that that process is not killed if at the clean
Zbigniew Jędrzejewski-Szmek 4f9456
-                end of the session it closes the FIFO. Hence, with
Zbigniew Jędrzejewski-Szmek 4f9456
-                this call explicitly turn off the FIFO logic, so that
Zbigniew Jędrzejewski-Szmek 4f9456
-                the PAM code can finish clean up on its own */
Zbigniew Jędrzejewski-Szmek 4f9456
-                session_remove_fifo(session);
Zbigniew Jędrzejewski-Szmek 4f9456
+                session_release(session);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
                 reply = dbus_message_new_method_return(message);
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (!reply)
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -2550,7 +2544,6 @@ int manager_start_scope(
Zbigniew Jędrzejewski-Szmek 4f9456
                 const char *slice,
Zbigniew Jędrzejewski-Szmek 4f9456
                 const char *description,
Zbigniew Jędrzejewski-Szmek 4f9456
                 const char *after,
Zbigniew Jędrzejewski-Szmek 4f9456
-                const char *kill_mode,
Zbigniew Jędrzejewski-Szmek 4f9456
                 DBusError *error,
Zbigniew Jędrzejewski-Szmek 4f9456
                 char **job) {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -2622,18 +2615,6 @@ int manager_start_scope(
Zbigniew Jędrzejewski-Szmek 4f9456
                         return log_oom();
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        if (!isempty(kill_mode)) {
Zbigniew Jędrzejewski-Szmek 4f9456
-                const char *kill_mode_property = "KillMode";
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
Zbigniew Jędrzejewski-Szmek 4f9456
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &kill_mode_property) ||
Zbigniew Jędrzejewski-Szmek 4f9456
-                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
Zbigniew Jędrzejewski-Szmek 4f9456
-                    !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &kill_mode) ||
Zbigniew Jędrzejewski-Szmek 4f9456
-                    !dbus_message_iter_close_container(&sub2, &sub3) ||
Zbigniew Jędrzejewski-Szmek 4f9456
-                    !dbus_message_iter_close_container(&sub, &sub2))
Zbigniew Jędrzejewski-Szmek 4f9456
-                        return log_oom();
Zbigniew Jędrzejewski-Szmek 4f9456
-        }
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
         /* cgroup empty notification is not available in containers
Zbigniew Jędrzejewski-Szmek 4f9456
          * currently. To make this less problematic, let's shorten the
Zbigniew Jędrzejewski-Szmek 4f9456
          * stop timeout for sessions, so that we don't wait
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -2792,6 +2773,36 @@ int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char
Zbigniew Jędrzejewski-Szmek 4f9456
         return 1;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+int manager_abandon_scope(Manager *manager, const char *scope, DBusError *error) {
Zbigniew Jędrzejewski-Szmek 4f9456
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
+        _cleanup_free_ char *path = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
+        int r;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        assert(manager);
Zbigniew Jędrzejewski-Szmek 4f9456
+        assert(scope);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        path = unit_dbus_path_from_name(scope);
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (!path)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        r = bus_method_call_with_reply(
Zbigniew Jędrzejewski-Szmek 4f9456
+                manager->bus,
Zbigniew Jędrzejewski-Szmek 4f9456
+                "org.freedesktop.systemd1",
Zbigniew Jędrzejewski-Szmek 4f9456
+                path,
Zbigniew Jędrzejewski-Szmek 4f9456
+                "org.freedesktop.systemd1.Scope",
Zbigniew Jędrzejewski-Szmek 4f9456
+                "Abandon",
Zbigniew Jędrzejewski-Szmek 4f9456
+                &reply,
Zbigniew Jędrzejewski-Szmek 4f9456
+                error,
Zbigniew Jędrzejewski-Szmek 4f9456
+                DBUS_TYPE_INVALID);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                log_error("Failed to abandon scope %s", scope);
Zbigniew Jędrzejewski-Szmek 4f9456
+                return r;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        return 1;
Zbigniew Jędrzejewski-Szmek 4f9456
+}
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error) {
Zbigniew Jędrzejewski-Szmek 4f9456
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
         const char *w;
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index 27aa335142..78e6d74cda 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -24,6 +24,7 @@
Zbigniew Jędrzejewski-Szmek 4f9456
 #include <unistd.h>
Zbigniew Jędrzejewski-Szmek 4f9456
 #include <sys/epoll.h>
Zbigniew Jędrzejewski-Szmek 4f9456
 #include <fcntl.h>
Zbigniew Jędrzejewski-Szmek 4f9456
+#include <sys/timerfd.h>
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
 #include <systemd/sd-id128.h>
Zbigniew Jędrzejewski-Szmek 4f9456
 #include <systemd/sd-messages.h>
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -36,6 +37,8 @@
Zbigniew Jędrzejewski-Szmek 4f9456
 #include "dbus-common.h"
Zbigniew Jędrzejewski-Szmek 4f9456
 #include "logind-session.h"
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+#define RELEASE_SEC 20
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
 static unsigned devt_hash_func(const void *p) {
Zbigniew Jędrzejewski-Szmek 4f9456
         uint64_t u = *(const dev_t*)p;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -505,7 +508,6 @@ static int session_start_scope(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (!s->scope) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 _cleanup_free_ char *description = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
-                const char *kill_mode;
Zbigniew Jędrzejewski-Szmek 4f9456
                 char *scope, *job;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
                 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -516,9 +518,7 @@ static int session_start_scope(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (!scope)
Zbigniew Jędrzejewski-Szmek 4f9456
                         return log_oom();
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-                kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
-                r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job;;
Zbigniew Jędrzejewski-Szmek 4f9456
+                r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", &error, &job;;
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
                         log_error("Failed to start session scope %s: %s %s",
Zbigniew Jędrzejewski-Szmek 4f9456
                                   scope, bus_error(&error, r), error.name);
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -579,23 +579,22 @@ int session_start(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         s->started = true;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        /* Save session data */
Zbigniew Jędrzejewski-Szmek 4f9456
+        /* Save data */
Zbigniew Jędrzejewski-Szmek 4f9456
         session_save(s);
Zbigniew Jędrzejewski-Szmek 4f9456
         user_save(s->user);
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->seat)
Zbigniew Jędrzejewski-Szmek 4f9456
+                seat_save(s->seat);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        /* Send signals */
Zbigniew Jędrzejewski-Szmek 4f9456
         session_send_signal(s, true);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (s->seat) {
Zbigniew Jędrzejewski-Szmek 4f9456
-                seat_save(s->seat);
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (s->seat->active == s)
Zbigniew Jędrzejewski-Szmek 4f9456
                         seat_send_changed(s->seat, "Sessions\0ActiveSession\0");
Zbigniew Jędrzejewski-Szmek 4f9456
                 else
Zbigniew Jędrzejewski-Szmek 4f9456
                         seat_send_changed(s->seat, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        user_send_changed(s->user, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
         return 0;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -611,15 +610,24 @@ static int session_stop_scope(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         if (!s->scope)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return 0;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        r = manager_stop_unit(s->manager, s->scope, &error, &job;;
Zbigniew Jędrzejewski-Szmek 4f9456
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
-                log_error("Failed to stop session scope: %s", bus_error(&error, r));
Zbigniew Jędrzejewski-Szmek 4f9456
-                dbus_error_free(&error);
Zbigniew Jędrzejewski-Szmek 4f9456
-                return r;
Zbigniew Jędrzejewski-Szmek 4f9456
-        }
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (manager_shall_kill(s->manager, s->user->name)) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                r = manager_stop_unit(s->manager, s->scope, &error, &job;;
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                        log_error("Failed to stop session scope: %s", bus_error(&error, r));
Zbigniew Jędrzejewski-Szmek 4f9456
+                        dbus_error_free(&error);
Zbigniew Jędrzejewski-Szmek 4f9456
+                        return r;
Zbigniew Jędrzejewski-Szmek 4f9456
+                }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        free(s->scope_job);
Zbigniew Jędrzejewski-Szmek 4f9456
-        s->scope_job = job;
Zbigniew Jędrzejewski-Szmek 4f9456
+                free(s->scope_job);
Zbigniew Jędrzejewski-Szmek 4f9456
+                s->scope_job = job;
Zbigniew Jędrzejewski-Szmek 4f9456
+        } else {
Zbigniew Jędrzejewski-Szmek 4f9456
+                r = manager_abandon_scope(s->manager, s->scope, &error);
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                        log_error("Failed to abandon session scope: %s", bus_error(&error, r));
Zbigniew Jędrzejewski-Szmek 4f9456
+                        dbus_error_free(&error);
Zbigniew Jędrzejewski-Szmek 4f9456
+                        return r;
Zbigniew Jędrzejewski-Szmek 4f9456
+                }
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         return 0;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -644,6 +652,19 @@ static int session_unlink_x11_socket(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         return r < 0 ? -errno : 0;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+static void session_close_timer_fd(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
+        assert(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->timer_fd <= 0)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        hashmap_remove(s->manager->timer_fds, INT_TO_PTR(s->timer_fd + 1));
Zbigniew Jędrzejewski-Szmek 4f9456
+        epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->timer_fd, NULL);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        close_nointr(s->timer_fd);
Zbigniew Jędrzejewski-Szmek 4f9456
+        s->timer_fd = -1;
Zbigniew Jędrzejewski-Szmek 4f9456
+}
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_stop(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         int r;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -652,11 +673,18 @@ int session_stop(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         if (!s->user)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return -ESTALE;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        session_close_timer_fd(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        /* We are going down, don't care about FIFOs anymore */
Zbigniew Jędrzejewski-Szmek 4f9456
+        session_remove_fifo(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         /* Kill cgroup */
Zbigniew Jędrzejewski-Szmek 4f9456
         r = session_stop_scope(s);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         session_save(s);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        s->stopping = true;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         return r;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -678,6 +706,8 @@ int session_finalize(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
                            "MESSAGE=Removed session %s.", s->id,
Zbigniew Jędrzejewski-Szmek 4f9456
                            NULL);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        session_close_timer_fd(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         /* Kill session devices */
Zbigniew Jędrzejewski-Szmek 4f9456
         while ((sd = hashmap_first(s->devices)))
Zbigniew Jędrzejewski-Szmek 4f9456
                 session_device_free(sd);
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -698,16 +728,64 @@ int session_finalize(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 if (s->seat->active == s)
Zbigniew Jędrzejewski-Szmek 4f9456
                         seat_set_active(s->seat, NULL);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-                seat_send_changed(s->seat, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
                 seat_save(s->seat);
Zbigniew Jędrzejewski-Szmek 4f9456
+                seat_send_changed(s->seat, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        user_send_changed(s->user, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
         user_save(s->user);
Zbigniew Jędrzejewski-Szmek 4f9456
+        user_send_changed(s->user, "Sessions\0");
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         return r;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+void session_release(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
+        int r;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        struct itimerspec its = { .it_value.tv_sec = RELEASE_SEC };
Zbigniew Jędrzejewski-Szmek 4f9456
+        struct epoll_event ev = {};
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        assert(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (!s->started || s->stopping)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->timer_fd >= 0)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        s->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->timer_fd < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                log_error("Failed to create session release timer fd");
Zbigniew Jędrzejewski-Szmek 4f9456
+                goto out;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        r = hashmap_put(s->manager->timer_fds, INT_TO_PTR(s->timer_fd + 1), s);
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                log_error("Failed to store session release timer fd");
Zbigniew Jędrzejewski-Szmek 4f9456
+                goto out;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        ev.events = EPOLLONESHOT;
Zbigniew Jędrzejewski-Szmek 4f9456
+        ev.data.u32 = FD_OTHER_BASE + s->timer_fd;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        r = epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_ADD, s->timer_fd, &ev;;
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                log_error("Failed to add session release timer fd to epoll instance");
Zbigniew Jędrzejewski-Szmek 4f9456
+                goto out;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        r = timerfd_settime(s->timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                log_error("Failed to arm timer : %m");
Zbigniew Jędrzejewski-Szmek 4f9456
+                goto out;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+out:
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->timer_fd >= 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                close_nointr(s->timer_fd);
Zbigniew Jędrzejewski-Szmek 4f9456
+                s->timer_fd = -1;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+}
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
 bool session_is_active(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         assert(s);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -904,8 +982,6 @@ void session_remove_fifo(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_check_gc(Session *s, bool drop_not_started) {
Zbigniew Jędrzejewski-Szmek 4f9456
-        int r;
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
         assert(s);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (drop_not_started && !s->started)
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -915,11 +991,7 @@ int session_check_gc(Session *s, bool drop_not_started) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 return 0;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (s->fifo_fd >= 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
-                r = pipe_eof(s->fifo_fd);
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 4f9456
-                        return r;
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (r == 0)
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (pipe_eof(s->fifo_fd) <= 0)
Zbigniew Jędrzejewski-Szmek 4f9456
                         return 1;
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -945,15 +1017,15 @@ void session_add_to_gc_queue(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
 SessionState session_get_state(Session *s) {
Zbigniew Jędrzejewski-Szmek 4f9456
         assert(s);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s->stopping || s->timer_fd >= 0)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return SESSION_CLOSING;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         if (s->closing)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return SESSION_CLOSING;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (s->scope_job)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return SESSION_OPENING;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        if (s->fifo_fd < 0)
Zbigniew Jędrzejewski-Szmek 4f9456
-                return SESSION_CLOSING;
Zbigniew Jędrzejewski-Szmek 4f9456
-
Zbigniew Jędrzejewski-Szmek 4f9456
         if (session_is_active(s))
Zbigniew Jędrzejewski-Szmek 4f9456
                 return SESSION_ACTIVE;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 1cc3df
index f175a8995e..9b76582c21 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -98,11 +98,14 @@ struct Session {
Zbigniew Jędrzejewski-Szmek 4f9456
         int fifo_fd;
Zbigniew Jędrzejewski-Szmek 4f9456
         char *fifo_path;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        int timer_fd;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         bool idle_hint;
Zbigniew Jędrzejewski-Szmek 4f9456
         dual_timestamp idle_hint_timestamp;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         bool in_gc_queue:1;
Zbigniew Jędrzejewski-Szmek 4f9456
         bool started:1;
Zbigniew Jędrzejewski-Szmek 4f9456
+        bool stopping:1;
Zbigniew Jędrzejewski-Szmek 4f9456
         bool closing:1;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         DBusMessage *create_message;
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -130,6 +133,7 @@ void session_remove_fifo(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_start(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_stop(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_finalize(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
+void session_release(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_save(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_load(Session *s);
Zbigniew Jędrzejewski-Szmek 4f9456
 int session_kill(Session *s, KillWho who, int signo);
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index ddf19eb0b6..3aeac136e8 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind-user.c
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind-user.c
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -529,6 +529,8 @@ int user_stop(User *u) {
Zbigniew Jędrzejewski-Szmek 4f9456
         if (k < 0)
Zbigniew Jędrzejewski-Szmek 4f9456
                 r = k;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        u->stopping = true;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         user_save(u);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         return r;
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -650,22 +652,27 @@ void user_add_to_gc_queue(User *u) {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
 UserState user_get_state(User *u) {
Zbigniew Jędrzejewski-Szmek 4f9456
         Session *i;
Zbigniew Jędrzejewski-Szmek 4f9456
-        bool all_closing = true;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         assert(u);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (u->stopping)
Zbigniew Jędrzejewski-Szmek 4f9456
+                return USER_CLOSING;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         if (u->slice_job || u->service_job)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return USER_OPENING;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        LIST_FOREACH(sessions_by_user, i, u->sessions) {
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (session_is_active(i))
Zbigniew Jędrzejewski-Szmek 4f9456
-                        return USER_ACTIVE;
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (session_get_state(i) != SESSION_CLOSING)
Zbigniew Jędrzejewski-Szmek 4f9456
-                        all_closing = false;
Zbigniew Jędrzejewski-Szmek 4f9456
-        }
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (u->sessions) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                bool all_closing = true;
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+                LIST_FOREACH(sessions_by_user, i, u->sessions) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                        if (session_is_active(i))
Zbigniew Jędrzejewski-Szmek 4f9456
+                                return USER_ACTIVE;
Zbigniew Jędrzejewski-Szmek 4f9456
+                        if (session_get_state(i) != SESSION_CLOSING)
Zbigniew Jędrzejewski-Szmek 4f9456
+                                all_closing = false;
Zbigniew Jędrzejewski-Szmek 4f9456
+                }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        if (u->sessions)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return all_closing ? USER_CLOSING : USER_ONLINE;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (user_check_linger_file(u) > 0)
Zbigniew Jędrzejewski-Szmek 4f9456
                 return USER_LINGERING;
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
Zbigniew Jędrzejewski-Szmek 1cc3df
index a36f4565e8..a12532e229 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind-user.h
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind-user.h
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -61,6 +61,7 @@ struct User {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         bool in_gc_queue:1;
Zbigniew Jędrzejewski-Szmek 4f9456
         bool started:1;
Zbigniew Jędrzejewski-Szmek 4f9456
+        bool stopping:1;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         LIST_HEAD(Session, sessions);
Zbigniew Jędrzejewski-Szmek 4f9456
         LIST_FIELDS(User, gc_queue);
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind.c b/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index 0628032ae5..5180be7426 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -80,10 +80,11 @@ Manager *manager_new(void) {
Zbigniew Jędrzejewski-Szmek 4f9456
         m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
Zbigniew Jędrzejewski-Szmek 4f9456
         m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
Zbigniew Jędrzejewski-Szmek 4f9456
         m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
Zbigniew Jędrzejewski-Szmek 4f9456
+        m->timer_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
Zbigniew Jędrzejewski-Szmek 4f9456
             !m->user_units || !m->session_units ||
Zbigniew Jędrzejewski-Szmek 4f9456
-            !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
Zbigniew Jędrzejewski-Szmek 4f9456
+            !m->session_fds || !m->inhibitor_fds || !m->button_fds || !m->timer_fds) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 manager_free(m);
Zbigniew Jędrzejewski-Szmek 4f9456
                 return NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -149,6 +150,7 @@ void manager_free(Manager *m) {
Zbigniew Jędrzejewski-Szmek 4f9456
         hashmap_free(m->session_fds);
Zbigniew Jędrzejewski-Szmek 4f9456
         hashmap_free(m->inhibitor_fds);
Zbigniew Jędrzejewski-Szmek 4f9456
         hashmap_free(m->button_fds);
Zbigniew Jędrzejewski-Szmek 4f9456
+        hashmap_free(m->timer_fds);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         if (m->console_active_fd >= 0)
Zbigniew Jędrzejewski-Szmek 4f9456
                 close_nointr_nofail(m->console_active_fd);
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -620,6 +622,13 @@ static void manager_dispatch_other(Manager *m, int fd) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 return;
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+        s = hashmap_get(m->timer_fds, INT_TO_PTR(fd + 1));
Zbigniew Jędrzejewski-Szmek 4f9456
+        if (s) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                assert(s->timer_fd == fd);
Zbigniew Jędrzejewski-Szmek 4f9456
+                session_stop(s);
Zbigniew Jędrzejewski-Szmek 4f9456
+                return;
Zbigniew Jędrzejewski-Szmek 4f9456
+        }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
         i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
Zbigniew Jędrzejewski-Szmek 4f9456
         if (i) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 assert(i->fifo_fd == fd);
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -942,8 +951,12 @@ void manager_gc(Manager *m, bool drop_not_started) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
Zbigniew Jędrzejewski-Szmek 4f9456
                 session->in_gc_queue = false;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (session_check_gc(session, drop_not_started) == 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                /* First, if we are not closing yet, initiate stopping */
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (!session_check_gc(session, drop_not_started) &&
Zbigniew Jędrzejewski-Szmek 4f9456
+                    session_get_state(session) != SESSION_CLOSING)
Zbigniew Jędrzejewski-Szmek 4f9456
                         session_stop(session);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (!session_check_gc(session, drop_not_started)) {
Zbigniew Jędrzejewski-Szmek 4f9456
                         session_finalize(session);
Zbigniew Jędrzejewski-Szmek 4f9456
                         session_free(session);
Zbigniew Jędrzejewski-Szmek 4f9456
                 }
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -953,8 +966,11 @@ void manager_gc(Manager *m, bool drop_not_started) {
Zbigniew Jędrzejewski-Szmek 4f9456
                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
Zbigniew Jędrzejewski-Szmek 4f9456
                 user->in_gc_queue = false;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-                if (user_check_gc(user, drop_not_started) == 0) {
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (!user_check_gc(user, drop_not_started) &&
Zbigniew Jędrzejewski-Szmek 4f9456
+                    user_get_state(user) != USER_CLOSING)
Zbigniew Jędrzejewski-Szmek 4f9456
                         user_stop(user);
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+                if (!user_check_gc(user, drop_not_started)) {
Zbigniew Jędrzejewski-Szmek 4f9456
                         user_finalize(user);
Zbigniew Jędrzejewski-Szmek 4f9456
                         user_free(user);
Zbigniew Jędrzejewski-Szmek 4f9456
                 }
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -1032,6 +1048,7 @@ finish:
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         return r;
Zbigniew Jędrzejewski-Szmek 4f9456
 }
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_startup(Manager *m) {
Zbigniew Jędrzejewski-Szmek 4f9456
         int r;
Zbigniew Jędrzejewski-Szmek 4f9456
         Seat *seat;
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/logind.h b/src/login/logind.h
Zbigniew Jędrzejewski-Szmek 1cc3df
index 9e6296cb7e..0d2248fa53 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/logind.h
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/logind.h
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -88,6 +88,7 @@ struct Manager {
Zbigniew Jędrzejewski-Szmek 4f9456
         Hashmap *session_fds;
Zbigniew Jędrzejewski-Szmek 4f9456
         Hashmap *inhibitor_fds;
Zbigniew Jędrzejewski-Szmek 4f9456
         Hashmap *button_fds;
Zbigniew Jędrzejewski-Szmek 4f9456
+        Hashmap *timer_fds;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         usec_t inhibit_delay_max;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -183,9 +184,10 @@ int manager_send_changed(Manager *manager, const char *properties);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_dispatch_delayed(Manager *manager);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *kill_mode, DBusError *error, char **job);
Zbigniew Jędrzejewski-Szmek 4f9456
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, DBusError *error, char **job);
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_start_unit(Manager *manager, const char *unit, DBusError *error, char **job);
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job);
Zbigniew Jędrzejewski-Szmek 4f9456
+int manager_abandon_scope(Manager *manager, const char *scope, DBusError *error);
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error);
Zbigniew Jędrzejewski-Szmek 4f9456
 int manager_unit_is_active(Manager *manager, const char *unit);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
Zbigniew Jędrzejewski-Szmek 1cc3df
index 5baf1b73c0..6259450025 100644
Zbigniew Jędrzejewski-Szmek 4f9456
--- a/src/login/pam-module.c
Zbigniew Jędrzejewski-Szmek 4f9456
+++ b/src/login/pam-module.c
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -489,7 +489,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
Zbigniew Jędrzejewski-Szmek 4f9456
                 int flags,
Zbigniew Jędrzejewski-Szmek 4f9456
                 int argc, const char **argv) {
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
-        const void *p = NULL, *existing = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
+        const void *existing = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
         const char *id;
Zbigniew Jędrzejewski-Szmek 4f9456
         DBusConnection *bus = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
         DBusMessage *m = NULL, *reply = NULL;
Zbigniew Jędrzejewski-Szmek 4f9456
@@ -546,12 +546,15 @@ _public_ PAM_EXTERN int pam_sm_close_session(
Zbigniew Jędrzejewski-Szmek 4f9456
                 }
Zbigniew Jędrzejewski-Szmek 4f9456
         }
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
+
Zbigniew Jędrzejewski-Szmek 4f9456
+        /* Note that we are knowingly leaking the FIFO fd here. This
Zbigniew Jędrzejewski-Szmek 4f9456
+         * way, logind can watch us die. If we closed it here it would
Zbigniew Jędrzejewski-Szmek 4f9456
+         * not have any clue when that is completed. Given that one
Zbigniew Jędrzejewski-Szmek 4f9456
+         * cannot really have multiple PAM sessions open from the same
Zbigniew Jędrzejewski-Szmek 4f9456
+         * process this means we will leak one FD at max. */
Zbigniew Jędrzejewski-Szmek 4f9456
         r = PAM_SUCCESS;
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
 finish:
Zbigniew Jędrzejewski-Szmek 4f9456
-        pam_get_data(handle, "systemd.session-fd", &p);
Zbigniew Jędrzejewski-Szmek 4f9456
-        if (p)
Zbigniew Jędrzejewski-Szmek 4f9456
-                close_nointr(PTR_TO_INT(p) - 1);
Zbigniew Jędrzejewski-Szmek 4f9456
 
Zbigniew Jędrzejewski-Szmek 4f9456
         dbus_error_free(&error);
Zbigniew Jędrzejewski-Szmek 4f9456