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

9fa8e4
From cb356d992cec51cb87e2243edadec6a3d3348bd7 Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
9fa8e4
Date: Tue, 19 Jul 2016 16:54:43 -0400
9fa8e4
Subject: [PATCH 1/3] 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
-- 
9fa8e4
2.7.4
9fa8e4
9fa8e4
9fa8e4
From e35b483f4c32d4095ea0d67991fff1e2b8339f2c Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
9fa8e4
Date: Wed, 20 Jul 2016 11:43:45 -0400
9fa8e4
Subject: [PATCH 2/3] 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
9fa8e4
index e07d32e..bc4a7ea 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
-- 
9fa8e4
2.7.4
9fa8e4
9fa8e4
9fa8e4
From fa6bc4c99f49a9c6ccd5cf1728eabf71685c34d0 Mon Sep 17 00:00:00 2001
9fa8e4
From: Ray Strode <rstrode@redhat.com>
9fa8e4
Date: Wed, 20 Jul 2016 17:23:05 -0400
9fa8e4
Subject: [PATCH 3/3] slave: close display when we're done with it.
9fa8e4
9fa8e4
When we're done with the display we need to kill off any clients
9fa8e4
that are lingering and close our own connection to the display.
9fa8e4
---
9fa8e4
 configure.ac       |  2 +-
9fa8e4
 daemon/gdm-slave.c | 38 ++++++++++++++++++++++++++++++++++++++
9fa8e4
 2 files changed, 39 insertions(+), 1 deletion(-)
9fa8e4
9fa8e4
diff --git a/configure.ac b/configure.ac
9fa8e4
index a131535..1ac2801 100644
9fa8e4
--- a/configure.ac
9fa8e4
+++ b/configure.ac
9fa8e4
@@ -63,61 +63,61 @@ dnl ---------------------------------------------------------------------------
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
9fa8e4
 )
9fa8e4
 AC_SUBST(DAEMON_CFLAGS)
9fa8e4
 AC_SUBST(DAEMON_LIBS)
9fa8e4
 
9fa8e4
 GLIB_GSETTINGS
9fa8e4
 
9fa8e4
-PKG_CHECK_MODULES(XLIB, x11 xau xrandr, ,
9fa8e4
+PKG_CHECK_MODULES(XLIB, x11 xau xrandr x11-xcb, ,
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
             AS_HELP_STRING([--with-selinux],
9fa8e4
                            [Add SELinux support]),,
9fa8e4
             with_selinux=auto)
9fa8e4
 
9fa8e4
 PKG_CHECK_MODULES(LIBSELINUX, libselinux, have_selinux=yes, have_selinux=no)
9fa8e4
 
9fa8e4
 use_selinux=no
9fa8e4
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
9fa8e4
index b4bbcfd..3a22cc6 100644
9fa8e4
--- a/daemon/gdm-slave.c
9fa8e4
+++ b/daemon/gdm-slave.c
9fa8e4
@@ -11,65 +11,68 @@
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
 
9fa8e4
 #include <X11/Xlib.h> /* for Display */
9fa8e4
+#include <X11/Xlib-xcb.h>
9fa8e4
 #include <X11/Xatom.h> /* for XA_PIXMAP */
9fa8e4
 #include <X11/cursorfont.h> /* for watch cursor */
9fa8e4
 #include <X11/extensions/Xrandr.h>
9fa8e4
 #include <X11/Xatom.h>
9fa8e4
 
9fa8e4
+#include <xcb/xcb.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
 
9fa8e4
         Display         *server_display;
9fa8e4
 
9fa8e4
         char            *session_id;
9fa8e4
 
9fa8e4
         GdmDisplay      *display;
9fa8e4
 
9fa8e4
         /* cached display values */
9fa8e4
         char            *display_name;
9fa8e4
         int              display_number;
9fa8e4
@@ -453,60 +456,95 @@ gdm_slave_real_start (GdmSlave *slave)
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
 
9fa8e4
         g_clear_object (&slave->priv->display);
9fa8e4
 
9fa8e4
+        if (slave->priv->server_display) {
9fa8e4
+                xcb_connection_t *connection;
9fa8e4
+                const xcb_setup_t *setup;
9fa8e4
+
9fa8e4
+                /* These 3 bits are reserved/unused by the X protocol */
9fa8e4
+                guint32 unused_bits = 0b11100000000000000000000000000000;
9fa8e4
+                XID highest_client, client;
9fa8e4
+                guint32 client_increment;
9fa8e4
+
9fa8e4
+                connection = XGetXCBConnection (slave->priv->server_display);
9fa8e4
+                setup = xcb_get_setup (connection);
9fa8e4
+
9fa8e4
+                /* resource_id_mask is the bits given to each client for
9fa8e4
+                 * addressing resources */
9fa8e4
+                highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
9fa8e4
+                client_increment = setup->resource_id_mask + 1;
9fa8e4
+
9fa8e4
+                gdm_error_trap_push ();
9fa8e4
+
9fa8e4
+                /* Kill every client but ourselves, then close our own connection
9fa8e4
+                 */
9fa8e4
+                for (client = 0;
9fa8e4
+                     client <= highest_client;
9fa8e4
+                     client += client_increment) {
9fa8e4
+
9fa8e4
+                        if (client != setup->resource_id_base)
9fa8e4
+                                XKillClient (slave->priv->server_display, client);
9fa8e4
+                }
9fa8e4
+
9fa8e4
+                XCloseDisplay (slave->priv->server_display);
9fa8e4
+                gdm_error_trap_pop ();
9fa8e4
+
9fa8e4
+                slave->priv->server_display = NULL;
9fa8e4
+        }
9fa8e4
+
9fa8e4
         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
 
9fa8e4
-- 
9fa8e4
2.7.4
9fa8e4