Zbigniew Jędrzejewski-Szmek 62fe94
From 2ec3ff668ff03410e94cfef8e3ee9384a8222211 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Fri, 19 Sep 2014 13:26:39 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] login: pause devices before acknowledging VT switches
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
If a session controller does not need synchronous VT switches, we allow
Zbigniew Jędrzejewski-Szmek 62fe94
them to pass VT control to logind, which acknowledges all VT switches
Zbigniew Jędrzejewski-Szmek 62fe94
unconditionally. This works fine with all sessions using the dbus API,
Zbigniew Jędrzejewski-Szmek 62fe94
but causes out-of-sync device use if we switch to legacy sessions that
Zbigniew Jędrzejewski-Szmek 62fe94
are notified via VT signals. Those are processed before logind notices
Zbigniew Jędrzejewski-Szmek 62fe94
the session-switch via sysfs. Therefore, leaving the old session still
Zbigniew Jędrzejewski-Szmek 62fe94
active for a short amount of time.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
This, in fact, may cause the legacy session to prepare graphics devices
Zbigniew Jędrzejewski-Szmek 62fe94
before the old session was deactivated, and thus, maybe causing the old
Zbigniew Jędrzejewski-Szmek 62fe94
session to interfer with graphics device usage.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
Fix this by releasing devices immediately before acknowledging VT
Zbigniew Jędrzejewski-Szmek 62fe94
switches. This way, sessions without VT handlers are required to support
Zbigniew Jędrzejewski-Szmek 62fe94
async session switching (which they do in that case, anyway).
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/login/logind-session.c | 21 +++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/login/logind-session.h |  1 +
Zbigniew Jędrzejewski-Szmek 62fe94
 src/login/logind.c         |  4 ++--
Zbigniew Jędrzejewski-Szmek 62fe94
 3 files changed, 24 insertions(+), 2 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 62fe94
index eeb58c9031..477ac9ab1b 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/login/logind-session.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1053,6 +1053,27 @@ void session_restore_vt(Session *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
         s->vtfd = safe_close(s->vtfd);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+void session_leave_vt(Session *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* This is called whenever we get a VT-switch signal from the kernel.
Zbigniew Jędrzejewski-Szmek 62fe94
+         * We acknowledge all of them unconditionally. Note that session are
Zbigniew Jędrzejewski-Szmek 62fe94
+         * free to overwrite those handlers and we only register them for
Zbigniew Jędrzejewski-Szmek 62fe94
+         * sessions with controllers. Legacy sessions are not affected.
Zbigniew Jędrzejewski-Szmek 62fe94
+         * However, if we switch from a non-legacy to a legacy session, we must
Zbigniew Jędrzejewski-Szmek 62fe94
+         * make sure to pause all device before acknowledging the switch. We
Zbigniew Jędrzejewski-Szmek 62fe94
+         * process the real switch only after we are notified via sysfs, so the
Zbigniew Jędrzejewski-Szmek 62fe94
+         * legacy session might have already started using the devices. If we
Zbigniew Jędrzejewski-Szmek 62fe94
+         * don't pause the devices before the switch, we might confuse the
Zbigniew Jędrzejewski-Szmek 62fe94
+         * session we switch to. */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (s->vtfd < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                return;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        session_device_pause_all(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+        ioctl(s->vtfd, VT_RELDISP, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 bool session_is_controller(Session *s, const char *sender) {
Zbigniew Jędrzejewski-Szmek 62fe94
         assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 62fe94
index 9fb0188a84..a007fb5e84 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/login/logind-session.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -174,6 +174,7 @@ KillWho kill_who_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int session_prepare_vt(Session *s);
Zbigniew Jędrzejewski-Szmek 62fe94
 void session_restore_vt(Session *s);
Zbigniew Jędrzejewski-Szmek 62fe94
+void session_leave_vt(Session *s);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 bool session_is_controller(Session *s, const char *sender);
Zbigniew Jędrzejewski-Szmek 62fe94
 int session_set_controller(Session *s, const char *sender, bool force);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/login/logind.c b/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 62fe94
index f1b6a86298..8f00c46339 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/login/logind.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -750,11 +750,11 @@ static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (active->vtfd >= 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                ioctl(active->vtfd, VT_RELDISP, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+                session_leave_vt(active);
Zbigniew Jędrzejewski-Szmek 62fe94
         } else {
Zbigniew Jędrzejewski-Szmek 62fe94
                 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                                ioctl(iter->vtfd, VT_RELDISP, 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+                                session_leave_vt(iter);
Zbigniew Jędrzejewski-Szmek 62fe94
                                 break;
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94
                 }