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