[gdm/wip/systemd-activation: 4/4] worker: reuse user's VT if available



commit f1a6359fdf63b1d335eb6740c50d4f335bd18ea2
Author: Ray Strode <rstrode redhat com>
Date:   Mon Apr 28 16:21:47 2014 -0400

    worker: reuse user's VT if available
    
    When a user logs out, their session goes into the closing
    state until all processes from the session exit. The X server
    won't exit while the session is in the closing state, but will
    instead reset itself.  When the user logs in again, we need to
    select the same VT so the already running X server can properly
    manage the new session.
    
    This commit checks for the above scenario and tries to account
    for it.

 daemon/gdm-session-worker.c |  113 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 3 deletions(-)
---
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index c3de148..026bdef 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -52,6 +52,7 @@
 
 #ifdef WITH_SYSTEMD
 #include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
 #endif
 
 #ifdef ENABLE_SYSTEMD_JOURNAL
@@ -1984,6 +1985,106 @@ gdm_session_worker_start_session (GdmSessionWorker  *worker,
 
 #ifdef ENABLE_WAYLAND_SUPPORT
 static gboolean
+validate_session (GdmSessionWorker *worker,
+                  const char       *session,
+                  const char       *requested_seat,
+                  const char       *requested_type,
+                  const char       *requested_state)
+{
+    int ret;
+    gboolean validated = FALSE;
+    char *state = NULL, *type = NULL, *seat = NULL;
+    uid_t uid;
+    unsigned int vt;
+
+    ret = sd_session_get_uid (session, &uid);
+
+    if (ret < 0 || uid != worker->priv->uid) {
+            goto out;
+    }
+
+    ret = sd_session_get_state (session, &state);
+
+    if (ret < 0 || state == NULL) {
+            goto out;
+    }
+
+    if (strcmp (state, requested_state) != 0) {
+            goto out;
+    }
+
+    ret = sd_session_get_type (session, &type);
+
+    if (ret < 0 || type == NULL) {
+            goto out;
+    }
+
+    if (strcmp (type, requested_type) != 0) {
+            goto out;
+    }
+
+    ret = sd_session_get_seat (session, &seat);
+
+    if (ret < 0 || seat == NULL) {
+            goto out;
+    }
+
+    if (strcmp (seat, requested_seat) != 0) {
+            goto out;
+    }
+
+    ret = sd_session_get_vt (session, &vt);
+
+    if (ret < 0 || vt <= 0) {
+            goto out;
+    }
+
+    validated = TRUE;
+
+out:
+    free (state);
+    free (type);
+    free (seat);
+    return validated;
+}
+
+static int
+find_vt_of_closing_session (GdmSessionWorker *worker)
+{
+        char **sessions = NULL;
+        char *session = NULL;
+        unsigned int vt = 0;
+        int ret;
+        int i;
+
+        ret = sd_seat_get_sessions (worker->priv->display_seat_id, &sessions, NULL, NULL);
+
+        if (ret < 0 || sessions == NULL) {
+                goto out;
+        }
+
+        for (i = 0; sessions[i] != NULL; i++) {
+                if (vt == 0) {
+                        gboolean validated;
+                        validated = validate_session (worker, sessions[i], worker->priv->display_seat_id, 
"x11", "closing");
+
+                        if (validated) {
+                                ret = sd_session_get_vt (session, &vt);
+
+                                if (ret < 0) {
+                                        vt = 0;
+                                }
+                        }
+                }
+                free(sessions[i]);
+        }
+        free (sessions);
+
+out:
+        return (int) vt;
+}
+
+static gboolean
 set_up_for_new_vt (GdmSessionWorker *worker)
 {
         int fd;
@@ -2004,9 +2105,15 @@ set_up_for_new_vt (GdmSessionWorker *worker)
                 goto fail;
         }
 
-        if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
-                g_debug ("GdmSessionWorker: couldn't open new VT: %m");
-                goto fail;
+        /* First adopt any pre-existing VT own by a session going down
+         */
+        session_vt = find_vt_of_closing_session (worker);
+
+        if (session_vt <= 0) {
+                if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
+                        g_debug ("GdmSessionWorker: couldn't open new VT: %m");
+                        goto fail;
+                }
         }
 
         worker->priv->login_vt = vt_state.v_active;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]