Blame SOURCES/notify-xdmcp-about-session-end.patch

2e9516
From 4e4918c7d6dea3f03f3ae49f2d5721beb03936f2 Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
9fa8e4
Date: Tue, 19 Jul 2016 16:54:43 -0400
2e9516
Subject: [PATCH 1/5] xdmcp-display-factory: notify remote display when session
9fa8e4
 ended
9fa8e4
9fa8e4
gnome-shell and the session dbus daemon don't automatically exit
9fa8e4
when gnome-session does.  They, instead, wait for the display to
9fa8e4
exit or regenerate. If the display is remote, that won't happen
9fa8e4
until the keep alive timeout.
9fa8e4
9fa8e4
This commit changes GDM to explicitly notify the remote display
9fa8e4
when the session is over, so that it can regenerate immediately.
9fa8e4
---
9fa8e4
 daemon/gdm-xdmcp-display-factory.c | 15 ++++++++++++++-
9fa8e4
 1 file changed, 14 insertions(+), 1 deletion(-)
9fa8e4
9fa8e4
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
9fa8e4
index d01f7ff..4132dd1 100644
9fa8e4
--- a/daemon/gdm-xdmcp-display-factory.c
9fa8e4
+++ b/daemon/gdm-xdmcp-display-factory.c
9fa8e4
@@ -183,61 +183,64 @@ struct GdmXdmcpDisplayFactoryPrivate
9fa8e4
         /* configuration */
9fa8e4
         guint            port;
9fa8e4
         gboolean         use_multicast;
9fa8e4
         char            *multicast_address;
9fa8e4
         gboolean         honor_indirect;
9fa8e4
         char            *willing_script;
9fa8e4
         guint            max_displays_per_host;
9fa8e4
         guint            max_displays;
9fa8e4
         guint            max_pending_displays;
9fa8e4
         guint            max_wait;
9fa8e4
         guint            max_wait_indirect;
9fa8e4
 };
9fa8e4
 
9fa8e4
 enum {
9fa8e4
         PROP_0,
9fa8e4
         PROP_PORT,
9fa8e4
         PROP_USE_MULTICAST,
9fa8e4
         PROP_MULTICAST_ADDRESS,
9fa8e4
         PROP_HONOR_INDIRECT,
9fa8e4
         PROP_WILLING_SCRIPT,
9fa8e4
         PROP_MAX_DISPLAYS_PER_HOST,
9fa8e4
         PROP_MAX_DISPLAYS,
9fa8e4
         PROP_MAX_PENDING_DISPLAYS,
9fa8e4
         PROP_MAX_WAIT,
9fa8e4
         PROP_MAX_WAIT_INDIRECT,
9fa8e4
 };
9fa8e4
 
9fa8e4
 static void     gdm_xdmcp_display_factory_class_init    (GdmXdmcpDisplayFactoryClass *klass);
9fa8e4
 static void     gdm_xdmcp_display_factory_init          (GdmXdmcpDisplayFactory      *manager);
9fa8e4
 static void     gdm_xdmcp_display_factory_finalize      (GObject                     *object);
9fa8e4
-
9fa8e4
+static void     gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory,
9fa8e4
+                                      GdmAddress             *address,
9fa8e4
+                                      CARD16                  dspnum,
9fa8e4
+                                      CARD32                  sessid);
9fa8e4
 static gpointer xdmcp_display_factory_object = NULL;
9fa8e4
 
9fa8e4
 G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY)
9fa8e4
 
9fa8e4
 /* Theory of operation:
9fa8e4
  *
9fa8e4
  * Process idles waiting for UDP packets on port 177.
9fa8e4
  * Incoming packets are decoded and checked against tcp_wrapper.
9fa8e4
  *
9fa8e4
  * A typical session looks like this:
9fa8e4
  *
9fa8e4
  * Display sends Query/BroadcastQuery to Manager.
9fa8e4
  *
9fa8e4
  * Manager selects an appropriate authentication scheme from the
9fa8e4
  * display's list of supported ones and sends Willing/Unwilling.
9fa8e4
  *
9fa8e4
  * Assuming the display accepts the auth. scheme it sends back a
9fa8e4
  * Request.
9fa8e4
  *
9fa8e4
  * If the manager accepts to service the display (i.e. loadavg is low)
9fa8e4
  * it sends back an Accept containing a unique SessionID. The
9fa8e4
  * SessionID is stored in an accept queue by the Manager. Should the
9fa8e4
  * manager refuse to start a session a Decline is sent to the display.
9fa8e4
  *
9fa8e4
  * The display returns a Manage request containing the supplied
9fa8e4
  * SessionID. The manager will then start a session on the display. In
9fa8e4
  * case the SessionID is not on the accept queue the manager returns
9fa8e4
  * Refuse. If the manager fails to open the display for connections
9fa8e4
  * Failed is returned.
9fa8e4
  *
9fa8e4
@@ -2026,68 +2029,78 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
9fa8e4
                 g_warning ("Unable to get address: %s", gai_strerror (gaierr));
9fa8e4
                 g_free (xdmcp_port);
9fa8e4
                 return;
9fa8e4
         }
9fa8e4
         g_free (xdmcp_port);
9fa8e4
 
9fa8e4
         /* just take the first one */
9fa8e4
         ai = ai_list;
9fa8e4
 
9fa8e4
         if (ai != NULL) {
9fa8e4
                 char *ip;
9fa8e4
                 ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
9fa8e4
 
9fa8e4
                 ip = NULL;
9fa8e4
                 gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
9fa8e4
                 g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
9fa8e4
                         ip ? ip : "(null)");
9fa8e4
                 g_free (ip);
9fa8e4
         }
9fa8e4
 
9fa8e4
         freeaddrinfo (ai_list);
9fa8e4
 }
9fa8e4
 
9fa8e4
 static void
9fa8e4
 on_display_status_changed (GdmDisplay             *display,
9fa8e4
                            GParamSpec             *arg1,
9fa8e4
                            GdmXdmcpDisplayFactory *factory)
9fa8e4
 {
9fa8e4
         int              status;
9fa8e4
         GdmDisplayStore *store;
9fa8e4
+        GdmAddress *address;
9fa8e4
+        gint32  session_number;
9fa8e4
+        int display_number;
9fa8e4
 
9fa8e4
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
9fa8e4
 
9fa8e4
         status = gdm_display_get_status (display);
9fa8e4
 
9fa8e4
         g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
9fa8e4
         switch (status) {
9fa8e4
         case GDM_DISPLAY_FINISHED:
9fa8e4
+                g_object_get (display,
9fa8e4
+                              "remote-address", &address,
9fa8e4
+                              "x11-display-number", &display_number,
9fa8e4
+                              "session-number", &session_number,
9fa8e4
+                              NULL);
9fa8e4
+                gdm_xdmcp_send_alive (factory, address, display_number, session_number);
9fa8e4
+
9fa8e4
                 gdm_display_store_remove (store, display);
9fa8e4
                 break;
9fa8e4
         case GDM_DISPLAY_FAILED:
9fa8e4
                 gdm_display_store_remove (store, display);
9fa8e4
                 break;
9fa8e4
         case GDM_DISPLAY_UNMANAGED:
9fa8e4
                 break;
9fa8e4
         case GDM_DISPLAY_PREPARED:
9fa8e4
                 break;
9fa8e4
         case GDM_DISPLAY_MANAGED:
9fa8e4
                 break;
9fa8e4
         default:
9fa8e4
                 g_assert_not_reached ();
9fa8e4
                 break;
9fa8e4
         }
9fa8e4
 }
9fa8e4
 
9fa8e4
 static GdmDisplay *
9fa8e4
 gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
9fa8e4
                           const char             *hostname,
9fa8e4
                           GdmAddress             *address,
9fa8e4
                           int                     displaynum)
9fa8e4
 {
9fa8e4
         GdmDisplay      *display;
9fa8e4
         GdmDisplayStore *store;
9fa8e4
         gboolean         use_chooser;
9fa8e4
 
9fa8e4
         g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
9fa8e4
                 hostname ? hostname : "(null)", displaynum);
9fa8e4
 
9fa8e4
-- 
2e9516
2.9.3
9fa8e4
9fa8e4
2e9516
From 7b9f559b6b5c8217840e3441b4eb5a29080a19c4 Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
9fa8e4
Date: Wed, 20 Jul 2016 11:43:45 -0400
2e9516
Subject: [PATCH 2/5] worker: kill process group when session exits
9fa8e4
9fa8e4
Send a hangup signal to the session pg when it exits, so things
9fa8e4
have a chance to get cleaned up.
9fa8e4
---
9fa8e4
 daemon/gdm-session-worker.c | 2 ++
9fa8e4
 1 file changed, 2 insertions(+)
9fa8e4
9fa8e4
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
2e9516
index f37b92a..ffb728f 100644
9fa8e4
--- a/daemon/gdm-session-worker.c
9fa8e4
+++ b/daemon/gdm-session-worker.c
9fa8e4
@@ -1603,60 +1603,62 @@ run_script (GdmSessionWorker *worker,
9fa8e4
                                worker->priv->username,
9fa8e4
                                worker->priv->x11_display_name,
9fa8e4
                                worker->priv->display_is_local? NULL : worker->priv->hostname,
9fa8e4
                                worker->priv->x11_authority_file);
9fa8e4
 }
9fa8e4
 
9fa8e4
 static void
9fa8e4
 session_worker_child_watch (GPid              pid,
9fa8e4
                             int               status,
9fa8e4
                             GdmSessionWorker *worker)
9fa8e4
 {
9fa8e4
         g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
9fa8e4
                  (int) pid,
9fa8e4
                  WIFEXITED (status) ? "status"
9fa8e4
                  : WIFSIGNALED (status) ? "signal"
9fa8e4
                  : "unknown",
9fa8e4
                  WIFEXITED (status) ? WEXITSTATUS (status)
9fa8e4
                  : WIFSIGNALED (status) ? WTERMSIG (status)
9fa8e4
                  : -1);
9fa8e4
 
9fa8e4
 #ifdef WITH_CONSOLE_KIT
9fa8e4
         close_ck_session (worker);
9fa8e4
 #endif
9fa8e4
 
9fa8e4
         gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
9fa8e4
 
9fa8e4
         gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
9fa8e4
                                              worker->priv->service,
9fa8e4
                                              status);
9fa8e4
 
9fa8e4
+        killpg (pid, SIGHUP);
9fa8e4
+
9fa8e4
         worker->priv->child_pid = -1;
9fa8e4
 
9fa8e4
         run_script (worker, GDMCONFDIR "/PostSession");
9fa8e4
 }
9fa8e4
 
9fa8e4
 static void
9fa8e4
 gdm_session_worker_watch_child (GdmSessionWorker *worker)
9fa8e4
 {
9fa8e4
         g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
9fa8e4
         worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
9fa8e4
                                                           (GChildWatchFunc)session_worker_child_watch,
9fa8e4
                                                           worker);
9fa8e4
 
9fa8e4
 }
9fa8e4
 
9fa8e4
 static gboolean
9fa8e4
 _is_loggable_file (const char* filename)
9fa8e4
 {
9fa8e4
         struct stat file_info;
9fa8e4
 
9fa8e4
         if (g_lstat (filename, &file_info) < 0) {
9fa8e4
                 return FALSE;
9fa8e4
         }
9fa8e4
 
9fa8e4
         return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
9fa8e4
 }
9fa8e4
 
9fa8e4
 static void
9fa8e4
 rotate_logs (const char *path,
9fa8e4
              guint       n_copies)
9fa8e4
-- 
2e9516
2.9.3
9fa8e4
9fa8e4
2e9516
From ede6833989a691b0ee4a27834c572814564fc541 Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
2e9516
Date: Mon, 12 Dec 2016 10:35:32 -0500
2e9516
Subject: [PATCH 3/5] display: port GdmDisplay to xcb
9fa8e4
2e9516
Xlib will kill the process if it notices the display connection has
2e9516
gone away. This is suboptimal for the main gdm process!
2e9516
2e9516
This commit ports the Xlib code to xcb, so it won't have the above
2e9516
fragility.
2e9516
2e9516
https://bugzilla.gnome.org/show_bug.cgi?id=776059
9fa8e4
---
2e9516
 configure.ac       |   1 +
2e9516
 daemon/gdm-slave.c | 312 ++++++++++++++++++++++++-----------------------------
2e9516
 2 files changed, 142 insertions(+), 171 deletions(-)
9fa8e4
9fa8e4
diff --git a/configure.ac b/configure.ac
2e9516
index a131535..f9ad18a 100644
9fa8e4
--- a/configure.ac
9fa8e4
+++ b/configure.ac
2e9516
@@ -57,60 +57,61 @@ AC_SUBST(GETTEXT_PACKAGE)
2e9516
 AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package])
2e9516
 
2e9516
 dnl ---------------------------------------------------------------------------
2e9516
 dnl - Dependencies
2e9516
 dnl ---------------------------------------------------------------------------
2e9516
 
9fa8e4
 GLIB_REQUIRED_VERSION=2.36.0
9fa8e4
 GTK_REQUIRED_VERSION=2.91.1
9fa8e4
 LIBCANBERRA_GTK_REQUIRED_VERSION=0.4
9fa8e4
 ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.12
9fa8e4
 
9fa8e4
 EXTRA_COMPILE_WARNINGS(yes)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
9fa8e4
 AC_SUBST(GTHREAD_CFLAGS)
9fa8e4
 AC_SUBST(GTHREAD_LIBS)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(COMMON,
9fa8e4
         gobject-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
         gio-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
         gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
 )
9fa8e4
 AC_SUBST(COMMON_CFLAGS)
9fa8e4
 AC_SUBST(COMMON_LIBS)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(DAEMON,
9fa8e4
         gobject-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
         gio-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
         gio-unix-2.0 >= $GLIB_REQUIRED_VERSION
9fa8e4
         accountsservice >= $ACCOUNTS_SERVICE_REQUIRED_VERSION
2e9516
+        xcb
9fa8e4
 )
9fa8e4
 AC_SUBST(DAEMON_CFLAGS)
9fa8e4
 AC_SUBST(DAEMON_LIBS)
9fa8e4
 
9fa8e4
 GLIB_GSETTINGS
9fa8e4
 
2e9516
 PKG_CHECK_MODULES(XLIB, x11 xau xrandr, ,
9fa8e4
   [AC_PATH_XTRA
9fa8e4
     if test "x$no_x" = xyes; then
9fa8e4
       AC_MSG_ERROR("no (requires X development libraries)")
9fa8e4
     else
9fa8e4
       XLIB_LIBS="$X_PRE_LIBS $X_LIBS -lXau -lX11 -lXext -lXrandr $X_EXTRA_LIBS"
9fa8e4
       XLIB_CFLAGS=$X_CFLAGS
9fa8e4
     fi])
9fa8e4
 AC_SUBST(XLIB_CFLAGS)
9fa8e4
 AC_SUBST(XLIB_LIBS)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(GTK,
9fa8e4
         gtk+-3.0 >= $GTK_REQUIRED_VERSION
9fa8e4
 )
9fa8e4
 AC_SUBST(GTK_CFLAGS)
9fa8e4
 AC_SUBST(GTK_LIBS)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(CANBERRA_GTK,
9fa8e4
         libcanberra-gtk3 >= $LIBCANBERRA_GTK_REQUIRED_VERSION
9fa8e4
 )
9fa8e4
 AC_SUBST(CANBERRA_GTK_CFLAGS)
9fa8e4
 AC_SUBST(CANBERRA_GTK_LIBS)
9fa8e4
 
9fa8e4
 AC_ARG_WITH(selinux,
9fa8e4
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
2e9516
index b4bbcfd..c0a53fe 100644
9fa8e4
--- a/daemon/gdm-slave.c
9fa8e4
+++ b/daemon/gdm-slave.c
2e9516
@@ -10,398 +10,358 @@
2e9516
  * This program is distributed in the hope that it will be useful,
9fa8e4
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9fa8e4
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9fa8e4
  * GNU General Public License for more details.
9fa8e4
  *
9fa8e4
  * You should have received a copy of the GNU General Public License
9fa8e4
  * along with this program; if not, write to the Free Software
9fa8e4
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
9fa8e4
  *
9fa8e4
  */
9fa8e4
 
9fa8e4
 #include "config.h"
9fa8e4
 
9fa8e4
 #include <stdlib.h>
9fa8e4
 #include <stdio.h>
9fa8e4
 #include <stdint.h>
9fa8e4
 #include <fcntl.h>
9fa8e4
 #include <unistd.h>
9fa8e4
 #include <string.h>
9fa8e4
 #include <sys/types.h>
9fa8e4
 #include <sys/wait.h>
9fa8e4
 #include <errno.h>
9fa8e4
 #include <pwd.h>
9fa8e4
 #include <grp.h>
9fa8e4
 
9fa8e4
 #include <glib.h>
9fa8e4
 #include <glib/gstdio.h>
9fa8e4
 #include <glib/gi18n.h>
9fa8e4
 #include <glib-object.h>
9fa8e4
 
2e9516
-#include <X11/Xlib.h> /* for Display */
2e9516
-#include <X11/Xatom.h> /* for XA_PIXMAP */
2e9516
+#include <xcb/xcb.h>
2e9516
+
9fa8e4
 #include <X11/cursorfont.h> /* for watch cursor */
9fa8e4
 #include <X11/extensions/Xrandr.h>
9fa8e4
 #include <X11/Xatom.h>
9fa8e4
 
9fa8e4
 #ifdef WITH_SYSTEMD
9fa8e4
 #include <systemd/sd-login.h>
9fa8e4
 #endif
9fa8e4
 
9fa8e4
 #include "gdm-common.h"
9fa8e4
 #include "gdm-xerrors.h"
9fa8e4
 
9fa8e4
 #include "gdm-slave.h"
9fa8e4
 #include "gdm-display.h"
9fa8e4
 #include "gdm-display-glue.h"
9fa8e4
 
9fa8e4
 #include "gdm-server.h"
9fa8e4
 
9fa8e4
 #define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate))
9fa8e4
 
9fa8e4
 struct GdmSlavePrivate
9fa8e4
 {
9fa8e4
         GPid             pid;
9fa8e4
         guint            output_watch_id;
9fa8e4
         guint            error_watch_id;
9fa8e4
 
2e9516
-        Display         *server_display;
2e9516
+        xcb_connection_t *xcb_connection;
2e9516
+        int               xcb_screen_number;
9fa8e4
 
9fa8e4
         char            *session_id;
9fa8e4
 
9fa8e4
         GdmDisplay      *display;
9fa8e4
 
9fa8e4
         /* cached display values */
9fa8e4
         char            *display_name;
9fa8e4
         int              display_number;
2e9516
         char            *display_hostname;
2e9516
         gboolean         display_is_local;
2e9516
         char            *display_seat_id;
2e9516
         char            *display_x11_authority_file;
2e9516
         char            *windowpath;
2e9516
         GBytes          *display_x11_cookie;
2e9516
         gboolean         display_is_initial;
2e9516
 };
2e9516
 
2e9516
 enum {
2e9516
         PROP_0,
2e9516
         PROP_SESSION_ID,
2e9516
         PROP_DISPLAY,
2e9516
         PROP_DISPLAY_NAME,
2e9516
         PROP_DISPLAY_NUMBER,
2e9516
         PROP_DISPLAY_HOSTNAME,
2e9516
         PROP_DISPLAY_IS_LOCAL,
2e9516
         PROP_DISPLAY_SEAT_ID,
2e9516
         PROP_DISPLAY_X11_AUTHORITY_FILE,
2e9516
         PROP_DISPLAY_IS_INITIAL,
2e9516
 };
2e9516
 
2e9516
 enum {
2e9516
         STARTED,
2e9516
         STOPPED,
2e9516
         LAST_SIGNAL
2e9516
 };
2e9516
 
2e9516
 static guint signals [LAST_SIGNAL] = { 0, };
2e9516
 
2e9516
 static void     gdm_slave_class_init    (GdmSlaveClass *klass);
2e9516
 static void     gdm_slave_init          (GdmSlave      *slave);
2e9516
 static void     gdm_slave_finalize      (GObject       *object);
2e9516
 
2e9516
 G_DEFINE_ABSTRACT_TYPE (GdmSlave, gdm_slave, G_TYPE_OBJECT)
2e9516
 
2e9516
 #define CURSOR_WATCH XC_watch
2e9516
 
2e9516
 GQuark
2e9516
 gdm_slave_error_quark (void)
2e9516
 {
2e9516
         static GQuark ret = 0;
2e9516
         if (ret == 0) {
2e9516
                 ret = g_quark_from_static_string ("gdm-slave-error-quark");
2e9516
         }
2e9516
 
2e9516
         return ret;
2e9516
 }
2e9516
 
2e9516
-static XRRScreenResources *
2e9516
-get_screen_resources (Display *dpy)
2e9516
+static xcb_screen_t *
2e9516
+get_screen (xcb_connection_t *connection,
2e9516
+            int               screen_number)
2e9516
 {
2e9516
-        int major = 0, minor = 0;
2e9516
+        xcb_screen_t *screen = NULL;
2e9516
+        xcb_screen_iterator_t iter;
2e9516
 
2e9516
-        if (!XRRQueryVersion(dpy, &major, &minor)) {
2e9516
-                return NULL;
2e9516
+        iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
2e9516
+        while (iter.rem) {
2e9516
+                if (screen_number == 0)
2e9516
+                        screen = iter.data;
2e9516
+                screen_number--;
2e9516
+                xcb_screen_next (&iter);
2e9516
         }
2e9516
 
2e9516
-        if (major > 1) {
2e9516
-                return NULL;
2e9516
+        if (screen != NULL) {
2e9516
+                return screen;
2e9516
         }
2e9516
 
2e9516
-        if (minor >= 3) {
2e9516
-                return XRRGetScreenResourcesCurrent (dpy,
2e9516
-                                                     DefaultRootWindow (dpy));
2e9516
+        return NULL;
2e9516
+}
2e9516
+
2e9516
+static xcb_window_t
2e9516
+get_root_window (xcb_connection_t *connection,
2e9516
+                 int               screen_number)
2e9516
+{
2e9516
+        xcb_screen_t *screen = NULL;
2e9516
+
2e9516
+        screen = get_screen (connection, screen_number);
2e9516
+
2e9516
+        if (screen != NULL) {
2e9516
+                return screen->root;
2e9516
         }
2e9516
 
2e9516
-        return XRRGetScreenResources (dpy, DefaultRootWindow (dpy));
2e9516
+        return XCB_WINDOW_NONE;
2e9516
 }
2e9516
 
2e9516
 static void
2e9516
 determine_initial_cursor_position (GdmSlave *slave,
2e9516
                                    int      *x,
2e9516
                                    int      *y)
2e9516
 {
2e9516
-        XRRScreenResources *resources;
2e9516
-        RROutput primary_output;
2e9516
-        int i;
2e9516
-
2e9516
-        /* If this function fails for whatever reason,
2e9516
-         * put the pointer in the lower right corner of the screen.
2e9516
-         */
2e9516
-        *x = .9 * DisplayWidth (slave->priv->server_display,
2e9516
-                                DefaultScreen (slave->priv->server_display));
2e9516
-        *y = .9 * DisplayHeight (slave->priv->server_display,
2e9516
-                                 DefaultScreen (slave->priv->server_display));
2e9516
-
2e9516
-        gdm_error_trap_push ();
2e9516
-        resources = get_screen_resources (slave->priv->server_display);
2e9516
-        primary_output = XRRGetOutputPrimary (slave->priv->server_display,
2e9516
-                                              DefaultRootWindow (slave->priv->server_display));
2e9516
-        gdm_error_trap_pop ();
2e9516
-
2e9516
-        if (resources == NULL) {
2e9516
-                return;
2e9516
-        }
2e9516
-
2e9516
-        for (i = 0; i < resources->noutput; i++) {
2e9516
-                XRROutputInfo *output_info;
2e9516
-
2e9516
-                if (primary_output == None) {
2e9516
-                        primary_output = resources->outputs[0];
2e9516
-                }
2e9516
-
2e9516
-                if (resources->outputs[i] != primary_output) {
2e9516
-                        continue;
2e9516
-                }
2e9516
-
2e9516
-                output_info = XRRGetOutputInfo (slave->priv->server_display,
2e9516
-                                                resources,
2e9516
-                                                resources->outputs[i]);
2e9516
-
2e9516
-                if (output_info->connection != RR_Disconnected &&
2e9516
-                    output_info->crtc != 0) {
2e9516
-                        XRRCrtcInfo *crtc_info;
2e9516
-
2e9516
-                        crtc_info = XRRGetCrtcInfo (slave->priv->server_display,
2e9516
-                                                    resources,
2e9516
-                                                    output_info->crtc);
2e9516
-                        /* position it sort of in the lower right
2e9516
-                         */
2e9516
-                        *x = crtc_info->x + .9 * crtc_info->width;
2e9516
-                        *y = crtc_info->y + .9 * crtc_info->height;
2e9516
-                        XRRFreeCrtcInfo (crtc_info);
2e9516
-                }
2e9516
-
2e9516
-                XRRFreeOutputInfo (output_info);
2e9516
-                break;
2e9516
-        }
2e9516
-
2e9516
-        XRRFreeScreenResources (resources);
2e9516
+        *x = 50;
2e9516
+        *y = 50;
2e9516
 }
2e9516
 
2e9516
 void
2e9516
 gdm_slave_set_initial_cursor_position (GdmSlave *slave)
2e9516
 {
2e9516
-        if (slave->priv->server_display != NULL) {
2e9516
+        if (slave->priv->xcb_connection != NULL) {
2e9516
                 int x, y;
2e9516
+                xcb_window_t root_window = XCB_WINDOW_NONE;
2e9516
 
2e9516
                 determine_initial_cursor_position (slave, &x, &y);
2e9516
-                XWarpPointer(slave->priv->server_display,
2e9516
-                             None,
2e9516
-                             DefaultRootWindow (slave->priv->server_display),
2e9516
-                             0, 0,
2e9516
-                             0, 0,
2e9516
-                             x, y);
2e9516
+
2e9516
+                root_window = get_root_window (slave->priv->xcb_connection,
2e9516
+                                               slave->priv->xcb_screen_number);
2e9516
+
2e9516
+                if (root_window != XCB_WINDOW_NONE) {
2e9516
+                        xcb_warp_pointer (slave->priv->xcb_connection,
2e9516
+                                          XCB_WINDOW_NONE,
2e9516
+                                          root_window,
2e9516
+                                          0, 0,
2e9516
+                                          0, 0,
2e9516
+                                          x, y);
2e9516
+                }
2e9516
         }
2e9516
 }
2e9516
 
2e9516
 static void
2e9516
-gdm_slave_setup_xhost_auth (XHostAddress *host_entries, XServerInterpretedAddress *si_entries)
2e9516
+gdm_slave_setup_xhost_auth (XHostAddress *host_entries)
2e9516
 {
2e9516
-        si_entries[0].type        = "localuser";
2e9516
-        si_entries[0].typelength  = strlen ("localuser");
2e9516
-        si_entries[1].type        = "localuser";
2e9516
-        si_entries[1].typelength  = strlen ("localuser");
2e9516
-        si_entries[2].type        = "localuser";
2e9516
-        si_entries[2].typelength  = strlen ("localuser");
2e9516
-
2e9516
-        si_entries[0].value       = "root";
2e9516
-        si_entries[0].valuelength = strlen ("root");
2e9516
-        si_entries[1].value       = GDM_USERNAME;
2e9516
-        si_entries[1].valuelength = strlen (GDM_USERNAME);
2e9516
-        si_entries[2].value       = "gnome-initial-setup";
2e9516
-        si_entries[2].valuelength = strlen ("gnome-initial-setup");
2e9516
-
2e9516
         host_entries[0].family    = FamilyServerInterpreted;
2e9516
-        host_entries[0].address   = (char *) &si_entries[0];
2e9516
-        host_entries[0].length    = sizeof (XServerInterpretedAddress);
2e9516
+        host_entries[0].address   = "localuser\0root";
2e9516
+        host_entries[0].length    = sizeof ("localuser\0root");
2e9516
         host_entries[1].family    = FamilyServerInterpreted;
2e9516
-        host_entries[1].address   = (char *) &si_entries[1];
2e9516
-        host_entries[1].length    = sizeof (XServerInterpretedAddress);
2e9516
+        host_entries[1].address   = "localuser\0" GDM_USERNAME;
2e9516
+        host_entries[1].length    = sizeof ("localuser\0" GDM_USERNAME);
2e9516
         host_entries[2].family    = FamilyServerInterpreted;
2e9516
-        host_entries[2].address   = (char *) &si_entries[2];
2e9516
-        host_entries[2].length    = sizeof (XServerInterpretedAddress);
2e9516
+        host_entries[2].address   = "localuser\0gnome-initial-setup";
2e9516
+        host_entries[2].length    = sizeof ("localuser\0gnome-initial-setup");
2e9516
 }
2e9516
 
2e9516
 static void
2e9516
 gdm_slave_set_windowpath (GdmSlave *slave)
2e9516
 {
2e9516
         /* setting WINDOWPATH for clients */
2e9516
-        Atom prop;
2e9516
-        Atom actualtype;
2e9516
-        int actualformat;
2e9516
-        unsigned long nitems;
2e9516
-        unsigned long bytes_after;
2e9516
-        unsigned char *buf;
2e9516
+        xcb_intern_atom_cookie_t atom_cookie;
2e9516
+        xcb_intern_atom_reply_t *atom_reply = NULL;
2e9516
+        xcb_get_property_cookie_t get_property_cookie;
2e9516
+        xcb_get_property_reply_t *get_property_reply = NULL;
2e9516
+        xcb_window_t root_window = XCB_WINDOW_NONE;
2e9516
         const char *windowpath;
2e9516
         char *newwindowpath;
2e9516
-        unsigned long num;
2e9516
+        uint32_t num;
2e9516
         char nums[10];
2e9516
         int numn;
2e9516
 
2e9516
-        prop = XInternAtom (slave->priv->server_display, "XFree86_VT", False);
2e9516
-        if (prop == None) {
2e9516
+        atom_cookie = xcb_intern_atom (slave->priv->xcb_connection, 0, strlen("XFree86_VT"), "XFree86_VT");
2e9516
+        atom_reply = xcb_intern_atom_reply (slave->priv->xcb_connection, atom_cookie, NULL);
2e9516
+
2e9516
+        if (atom_reply == NULL) {
2e9516
                 g_debug ("no XFree86_VT atom\n");
2e9516
-                return;
2e9516
+
2e9516
+                goto out;
2e9516
+        }
2e9516
+
2e9516
+        root_window = get_root_window (slave->priv->xcb_connection,
2e9516
+                                       slave->priv->xcb_screen_number);
2e9516
+
2e9516
+        if (root_window == XCB_WINDOW_NONE) {
2e9516
+                g_debug ("couldn't find root window\n");
2e9516
+                goto out;
2e9516
         }
2e9516
-        if (XGetWindowProperty (slave->priv->server_display,
2e9516
-                DefaultRootWindow (slave->priv->server_display), prop, 0, 1,
2e9516
-                False, AnyPropertyType, &actualtype, &actualformat,
2e9516
-                &nitems, &bytes_after, &buf)) {
2e9516
+
2e9516
+        get_property_cookie = xcb_get_property (slave->priv->xcb_connection,
2e9516
+                                                FALSE,
2e9516
+                                                root_window,
2e9516
+                                                atom_reply->atom,
2e9516
+                                                XCB_ATOM_INTEGER,
2e9516
+                                                0,
2e9516
+                                                1);
2e9516
+
2e9516
+        get_property_reply = xcb_get_property_reply (slave->priv->xcb_connection, get_property_cookie, NULL);
2e9516
+
2e9516
+        if (get_property_reply == NULL) {
2e9516
                 g_debug ("no XFree86_VT property\n");
2e9516
-                return;
2e9516
-        }
2e9516
-
2e9516
-        if (nitems != 1) {
2e9516
-                g_debug ("%lu items in XFree86_VT property!\n", nitems);
2e9516
-                XFree (buf);
2e9516
-                return;
2e9516
-        }
2e9516
-
2e9516
-        switch (actualtype) {
2e9516
-        case XA_CARDINAL:
2e9516
-        case XA_INTEGER:
2e9516
-        case XA_WINDOW:
2e9516
-                switch (actualformat) {
2e9516
-                case  8:
2e9516
-                        num = (*(uint8_t  *)(void *)buf);
2e9516
-                        break;
2e9516
-                case 16:
2e9516
-                        num = (*(uint16_t *)(void *)buf);
2e9516
-                        break;
2e9516
-                case 32:
2e9516
-                        num = (*(long *)(void *)buf);
2e9516
-                        break;
2e9516
-                default:
2e9516
-                        g_debug ("format %d in XFree86_VT property!\n", actualformat);
2e9516
-                        XFree (buf);
2e9516
-                        return;
2e9516
-                }
2e9516
-                break;
2e9516
-        default:
2e9516
-                g_debug ("type %lx in XFree86_VT property!\n", actualtype);
2e9516
-                XFree (buf);
2e9516
-                return;
2e9516
+                goto out;
2e9516
         }
2e9516
-        XFree (buf);
2e9516
+
2e9516
+        num = ((uint32_t *) xcb_get_property_value (get_property_reply))[0];
2e9516
 
2e9516
         windowpath = getenv ("WINDOWPATH");
2e9516
-        numn = snprintf (nums, sizeof (nums), "%lu", num);
2e9516
+
2e9516
+        numn = snprintf (nums, sizeof (nums), "%u", num);
2e9516
         if (!windowpath) {
2e9516
                 newwindowpath = malloc (numn + 1);
2e9516
                 sprintf (newwindowpath, "%s", nums);
2e9516
         } else {
2e9516
                 newwindowpath = malloc (strlen (windowpath) + 1 + numn + 1);
2e9516
                 sprintf (newwindowpath, "%s:%s", windowpath, nums);
2e9516
         }
2e9516
 
2e9516
-        slave->priv->windowpath = newwindowpath;
2e9516
-
2e9516
         g_setenv ("WINDOWPATH", newwindowpath, TRUE);
2e9516
+out:
2e9516
+        g_clear_pointer (&atom_reply, free);
2e9516
+        g_clear_pointer (&get_property_reply, free);
2e9516
 }
2e9516
 
2e9516
 gboolean
2e9516
 gdm_slave_connect_to_x11_display (GdmSlave *slave)
2e9516
 {
2e9516
+        xcb_auth_info_t *auth_info = NULL;
2e9516
         gboolean ret;
2e9516
 
2e9516
         ret = FALSE;
2e9516
 
2e9516
         /* We keep our own (windowless) connection (dsp) open to avoid the
2e9516
          * X server resetting due to lack of active connections. */
2e9516
 
2e9516
         g_debug ("GdmSlave: Server is ready - opening display %s", slave->priv->display_name);
2e9516
 
2e9516
         /* Give slave access to the display independent of current hostname */
2e9516
         if (slave->priv->display_x11_cookie != NULL) {
2e9516
-                XSetAuthorization ("MIT-MAGIC-COOKIE-1",
2e9516
-                                   strlen ("MIT-MAGIC-COOKIE-1"),
2e9516
-                                   (gpointer)
2e9516
-                                   g_bytes_get_data (slave->priv->display_x11_cookie, NULL),
2e9516
-                                   g_bytes_get_size (slave->priv->display_x11_cookie));
2e9516
+                auth_info = g_alloca (sizeof (xcb_auth_info_t));
2e9516
+
2e9516
+                auth_info->namelen = strlen ("MIT-MAGIC-COOKIE-1");
2e9516
+                auth_info->name = "MIT-MAGIC-COOKIE-1";
2e9516
+                auth_info->datalen = g_bytes_get_size (slave->priv->display_x11_cookie);
2e9516
+                auth_info->data = (gpointer) g_bytes_get_data (slave->priv->display_x11_cookie, NULL);
2e9516
         }
2e9516
 
2e9516
-        slave->priv->server_display = XOpenDisplay (slave->priv->display_name);
2e9516
+        slave->priv->xcb_connection = xcb_connect_to_display_with_auth_info (slave->priv->display_name,
2e9516
+                                                                             auth_info,
2e9516
+                                                                             &slave->priv->xcb_screen_number);
2e9516
 
2e9516
-        if (slave->priv->server_display == NULL) {
2e9516
+        if (xcb_connection_has_error (slave->priv->xcb_connection)) {
2e9516
+                g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
2e9516
                 g_warning ("Unable to connect to display %s", slave->priv->display_name);
2e9516
                 ret = FALSE;
2e9516
         } else if (slave->priv->display_is_local) {
2e9516
-                XServerInterpretedAddress si_entries[3];
2e9516
                 XHostAddress              host_entries[3];
2e9516
+                xcb_void_cookie_t         cookies[3];
2e9516
                 int                       i;
2e9516
 
2e9516
                 g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
2e9516
                 ret = TRUE;
2e9516
 
2e9516
                 /* Give programs run by the slave and greeter access to the
2e9516
                  * display independent of current hostname
2e9516
                  */
2e9516
-                gdm_slave_setup_xhost_auth (host_entries, si_entries);
2e9516
-
2e9516
-                gdm_error_trap_push ();
2e9516
+                gdm_slave_setup_xhost_auth (host_entries);
2e9516
 
2e9516
                 for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
2e9516
-                        XAddHost (slave->priv->server_display, &host_entries[i]);
2e9516
+                        cookies[i] = xcb_change_hosts_checked (slave->priv->xcb_connection,
2e9516
+                                                               XCB_HOST_MODE_INSERT,
2e9516
+                                                               host_entries[i].family,
2e9516
+                                                               host_entries[i].length,
2e9516
+                                                               (uint8_t *) host_entries[i].address);
2e9516
                 }
2e9516
 
2e9516
-                XSync (slave->priv->server_display, False);
2e9516
-                if (gdm_error_trap_pop ()) {
2e9516
-                        g_warning ("Failed to give slave programs access to the display. Trying to proceed.");
2e9516
+                for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
2e9516
+                        xcb_generic_error_t *xcb_error;
2e9516
+
2e9516
+                        xcb_error = xcb_request_check (slave->priv->xcb_connection, cookies[i]);
2e9516
+
2e9516
+                        if (xcb_error != NULL) {
2e9516
+                                g_debug ("Failed to give system user '%s' access to the display. Trying to proceed.", host_entries[i].address + sizeof ("localuser"));
2e9516
+                                free (xcb_error);
2e9516
+                        } else {
2e9516
+                                g_debug ("Gave system user '%s' access to the display.", host_entries[i].address + sizeof ("localuser"));
2e9516
+                        }
2e9516
                 }
2e9516
 
2e9516
                 gdm_slave_set_windowpath (slave);
2e9516
         } else {
2e9516
                 g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
2e9516
                 ret = TRUE;
2e9516
         }
2e9516
 
2e9516
         if (ret) {
2e9516
                 g_signal_emit (slave, signals [STARTED], 0);
2e9516
         }
2e9516
 
2e9516
         return ret;
2e9516
 }
2e9516
 
2e9516
 static gboolean
2e9516
 gdm_slave_real_start (GdmSlave *slave)
2e9516
 {
2e9516
         gboolean    res;
2e9516
         GError     *error;
2e9516
         const char *x11_cookie;
2e9516
         gsize       x11_cookie_size;
2e9516
 
2e9516
         g_debug ("GdmSlave: Starting slave");
2e9516
 
2e9516
         /* cache some values up front */
2e9516
         error = NULL;
2e9516
         res = gdm_display_is_local (slave->priv->display, &slave->priv->display_is_local, &error);
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to get value: %s", error->message);
2e9516
@@ -495,104 +455,114 @@ gdm_slave_start (GdmSlave *slave)
2e9516
         g_object_ref (slave);
2e9516
         ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
2e9516
         g_object_unref (slave);
2e9516
 
2e9516
         return ret;
2e9516
 }
2e9516
 
2e9516
 gboolean
2e9516
 gdm_slave_stop (GdmSlave *slave)
2e9516
 {
2e9516
         gboolean ret;
2e9516
 
2e9516
         g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
2e9516
 
2e9516
         g_debug ("GdmSlave: stopping slave");
2e9516
 
2e9516
         g_object_ref (slave);
2e9516
 
2e9516
         ret = GDM_SLAVE_GET_CLASS (slave)->stop (slave);
2e9516
         g_signal_emit (slave, signals [STOPPED], 0);
2e9516
 
2e9516
         g_object_unref (slave);
2e9516
         return ret;
2e9516
 }
2e9516
 
2e9516
 gboolean
2e9516
 gdm_slave_add_user_authorization (GdmSlave   *slave,
2e9516
                                   const char *username,
2e9516
                                   char      **filenamep)
2e9516
 {
2e9516
-        XServerInterpretedAddress si_entries[3];
2e9516
         XHostAddress              host_entries[3];
2e9516
+        xcb_void_cookie_t         cookies[3];
2e9516
         int                       i;
2e9516
         gboolean                  res;
2e9516
         GError                   *error;
2e9516
         char                     *filename;
2e9516
 
2e9516
         filename = NULL;
2e9516
 
2e9516
         if (filenamep != NULL) {
2e9516
                 *filenamep = NULL;
2e9516
         }
2e9516
 
2e9516
         g_debug ("GdmSlave: Requesting user authorization");
2e9516
 
2e9516
         error = NULL;
2e9516
         res = gdm_display_add_user_authorization (slave->priv->display,
2e9516
                                                   username,
2e9516
                                                   &filename,
2e9516
                                                   &error);
2e9516
 
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to add user authorization: %s", error->message);
2e9516
                 g_error_free (error);
2e9516
         } else {
2e9516
                 g_debug ("GdmSlave: Got user authorization: %s", filename);
2e9516
         }
2e9516
 
2e9516
         if (filenamep != NULL) {
2e9516
                 *filenamep = g_strdup (filename);
2e9516
         }
2e9516
         g_free (filename);
2e9516
 
2e9516
         /* Remove access for the programs run by slave and greeter now that the
2e9516
          * user session is starting.
2e9516
          */
2e9516
-        gdm_slave_setup_xhost_auth (host_entries, si_entries);
2e9516
-        gdm_error_trap_push ();
2e9516
+        gdm_slave_setup_xhost_auth (host_entries);
2e9516
         for (i = 0; i < G_N_ELEMENTS (host_entries); i++) {
2e9516
-                XRemoveHost (slave->priv->server_display, &host_entries[i]);
2e9516
+                cookies[i] = xcb_change_hosts_checked (slave->priv->xcb_connection,
2e9516
+                                                       XCB_HOST_MODE_DELETE,
2e9516
+                                                       host_entries[i].family,
2e9516
+                                                       host_entries[i].length,
2e9516
+                                                       (uint8_t *) host_entries[i].address);
2e9516
         }
2e9516
-        XSync (slave->priv->server_display, False);
2e9516
-        if (gdm_error_trap_pop ()) {
2e9516
-                g_warning ("Failed to remove slave program access to the display. Trying to proceed.");
2e9516
+
2e9516
+        for (i = 0; i < G_N_ELEMENTS (cookies); i++) {
2e9516
+                xcb_generic_error_t *xcb_error;
2e9516
+
2e9516
+                xcb_error = xcb_request_check (slave->priv->xcb_connection, cookies[i]);
2e9516
+
2e9516
+                if (xcb_error != NULL) {
2e9516
+                        g_warning ("Failed to remove greeter program access to the display. Trying to proceed.");
2e9516
+                        free (xcb_error);
2e9516
+                }
2e9516
         }
2e9516
 
2e9516
         return res;
2e9516
 }
2e9516
 
2e9516
 static char *
2e9516
 gdm_slave_parse_enriched_login (GdmSlave   *slave,
2e9516
                                 const char *username)
2e9516
 {
2e9516
         char     **argv;
2e9516
         int        username_len;
2e9516
         GPtrArray *env;
2e9516
         GError    *error;
2e9516
         gboolean   res;
2e9516
         char      *parsed_username;
2e9516
         char      *command;
2e9516
         char      *std_output;
2e9516
         char      *std_error;
2e9516
 
2e9516
         parsed_username = NULL;
2e9516
 
2e9516
         if (username == NULL || username[0] == '\0') {
2e9516
                 return NULL;
2e9516
         }
2e9516
 
2e9516
         /* A script may be used to generate the automatic/timed login name
2e9516
            based on the display/host by ending the name with the pipe symbol
2e9516
            '|'. */
2e9516
 
2e9516
         username_len = strlen (username);
2e9516
-- 
2e9516
2.9.3
2e9516
2e9516
2e9516
From 89b3bc7ba5fbfa0948a02644cbe031961435e23d Mon Sep 17 00:00:00 2001
2e9516
From: Ray Strode <rstrode@redhat.com>
2e9516
Date: Mon, 19 Dec 2016 10:56:27 -0500
2e9516
Subject: [PATCH 4/5] slave: close display connection when done with it
2e9516
2e9516
---
2e9516
 daemon/gdm-slave.c | 1 +
2e9516
 1 file changed, 1 insertion(+)
2e9516
2e9516
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
2e9516
index c0a53fe..cd26965 100644
2e9516
--- a/daemon/gdm-slave.c
2e9516
+++ b/daemon/gdm-slave.c
2e9516
@@ -411,60 +411,61 @@ gdm_slave_real_start (GdmSlave *slave)
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to get value: %s", error->message);
9fa8e4
                 g_error_free (error);
9fa8e4
                 return FALSE;
9fa8e4
         }
9fa8e4
 
9fa8e4
         error = NULL;
9fa8e4
         res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error);
9fa8e4
         if (! res) {
9fa8e4
                 g_warning ("Failed to get value: %s", error->message);
9fa8e4
                 g_error_free (error);
9fa8e4
                 return FALSE;
9fa8e4
         }
9fa8e4
 
9fa8e4
         error = NULL;
9fa8e4
         res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error);
9fa8e4
         if (! res) {
9fa8e4
                 g_warning ("Failed to get value: %s", error->message);
9fa8e4
                 g_error_free (error);
9fa8e4
                 return FALSE;
9fa8e4
         }
9fa8e4
 
9fa8e4
         return TRUE;
9fa8e4
 }
9fa8e4
 
9fa8e4
 static gboolean
9fa8e4
 gdm_slave_real_stop (GdmSlave *slave)
9fa8e4
 {
9fa8e4
         g_debug ("GdmSlave: Stopping slave");
9fa8e4
 
2e9516
+        g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
9fa8e4
         g_clear_object (&slave->priv->display);
9fa8e4
 
2e9516
         return TRUE;
2e9516
 }
2e9516
 
2e9516
 gboolean
2e9516
 gdm_slave_start (GdmSlave *slave)
2e9516
 {
2e9516
         gboolean ret;
2e9516
 
2e9516
         g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
2e9516
 
2e9516
         g_debug ("GdmSlave: starting slave");
2e9516
 
2e9516
         g_object_ref (slave);
2e9516
         ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
2e9516
         g_object_unref (slave);
2e9516
 
2e9516
         return ret;
2e9516
 }
2e9516
 
2e9516
 gboolean
2e9516
 gdm_slave_stop (GdmSlave *slave)
2e9516
 {
2e9516
         gboolean ret;
2e9516
 
2e9516
         g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
2e9516
 
2e9516
         g_debug ("GdmSlave: stopping slave");
2e9516
 
2e9516
-- 
2e9516
2.9.3
2e9516
2e9516
2e9516
From 122433b95dd3e099b300bce97ce1a5c99d7e2ccd Mon Sep 17 00:00:00 2001
2e9516
From: Ray Strode <rstrode@redhat.com>
2e9516
Date: Wed, 20 Jul 2016 17:23:05 -0400
2e9516
Subject: [PATCH 5/5] slave: kill off clients from display when finished
2e9516
2e9516
When we're done with the display we need to kill off any clients
2e9516
that are lingering and close our own connection to the display.
2e9516
2e9516
This is so, for instance, processes from the session don't
2e9516
stick around on a -noreset Xvnc server (or something)
2e9516
2e9516
https://bugzilla.gnome.org/show_bug.cgi?id=776059
2e9516
---
2e9516
 daemon/gdm-slave.c | 32 +++++++++++++++++++++++++++++---
2e9516
 1 file changed, 29 insertions(+), 3 deletions(-)
2e9516
2e9516
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
2e9516
index cd26965..d965d4c 100644
2e9516
--- a/daemon/gdm-slave.c
2e9516
+++ b/daemon/gdm-slave.c
2e9516
@@ -411,64 +411,90 @@ gdm_slave_real_start (GdmSlave *slave)
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to get value: %s", error->message);
2e9516
                 g_error_free (error);
2e9516
                 return FALSE;
2e9516
         }
2e9516
 
2e9516
         error = NULL;
2e9516
         res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error);
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to get value: %s", error->message);
2e9516
                 g_error_free (error);
2e9516
                 return FALSE;
2e9516
         }
2e9516
 
2e9516
         error = NULL;
2e9516
         res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error);
2e9516
         if (! res) {
2e9516
                 g_warning ("Failed to get value: %s", error->message);
2e9516
                 g_error_free (error);
2e9516
                 return FALSE;
2e9516
         }
2e9516
 
2e9516
         return TRUE;
2e9516
 }
2e9516
 
2e9516
 static gboolean
2e9516
 gdm_slave_real_stop (GdmSlave *slave)
2e9516
 {
2e9516
         g_debug ("GdmSlave: Stopping slave");
2e9516
 
2e9516
-        g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
2e9516
-        g_clear_object (&slave->priv->display);
2e9516
+        if (slave->priv->xcb_connection) {
2e9516
+               const xcb_setup_t *setup;
2e9516
 
2e9516
-        return TRUE;
2e9516
+               /* These 3 bits are reserved/unused by the X protocol */
2e9516
+               guint32 unused_bits = 0b11100000000000000000000000000000;
2e9516
+               XID highest_client, client;
2e9516
+               guint32 client_increment;
9fa8e4
+
2e9516
+               setup = xcb_get_setup (slave->priv->xcb_connection);
9fa8e4
+
2e9516
+               /* resource_id_mask is the bits given to each client for
2e9516
+                * addressing resources */
2e9516
+               highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
2e9516
+               client_increment = setup->resource_id_mask + 1;
9fa8e4
+
2e9516
+               /* Kill every client but ourselves, then close our own connection
2e9516
+                */
2e9516
+               for (client = 0;
2e9516
+                    client <= highest_client;
2e9516
+                    client += client_increment) {
9fa8e4
+
2e9516
+                       if (client != setup->resource_id_base)
2e9516
+                               xcb_kill_client (slave->priv->xcb_connection, client);
2e9516
+               }
2e9516
+               xcb_flush (slave->priv->xcb_connection);
2e9516
+               g_clear_pointer (&slave->priv->xcb_connection, xcb_disconnect);
2e9516
+       }
2e9516
+       g_clear_object (&slave->priv->display);
9fa8e4
+
2e9516
+       return TRUE;
9fa8e4
 }
9fa8e4
 
9fa8e4
 gboolean
9fa8e4
 gdm_slave_start (GdmSlave *slave)
9fa8e4
 {
9fa8e4
         gboolean ret;
9fa8e4
 
9fa8e4
         g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
9fa8e4
 
9fa8e4
         g_debug ("GdmSlave: starting slave");
9fa8e4
 
9fa8e4
         g_object_ref (slave);
9fa8e4
         ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
9fa8e4
         g_object_unref (slave);
9fa8e4
 
9fa8e4
         return ret;
9fa8e4
 }
9fa8e4
 
9fa8e4
 gboolean
9fa8e4
 gdm_slave_stop (GdmSlave *slave)
9fa8e4
 {
9fa8e4
         gboolean ret;
9fa8e4
 
9fa8e4
         g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
9fa8e4
 
9fa8e4
         g_debug ("GdmSlave: stopping slave");
9fa8e4
 
9fa8e4
         g_object_ref (slave);
9fa8e4
 
2e9516
         ret = GDM_SLAVE_GET_CLASS (slave)->stop (slave);
9fa8e4
-- 
2e9516
2.9.3
9fa8e4