[gdm/wip/wayland-rebase: 7/8] slave: add ability to reset launch environment



commit aaaafd1aa488a620a94b0cdbbf8a66b181eb8454
Author: Ray Strode <rstrode redhat com>
Date:   Thu Sep 19 15:20:43 2013 -0400

    slave: add ability to reset launch environment
    
    This is useful if we want to kill a greeter and start a new
    one on the same X server.

 daemon/gdm-display.c            |   47 +++++++++++++++++++++
 daemon/gdm-display.h            |    8 ++++
 daemon/gdm-launch-environment.c |   87 +++++++++++++++++++++++++++++++--------
 daemon/gdm-launch-environment.h |    2 +
 daemon/gdm-manager.c            |   51 +++++++++++++++++++++++
 daemon/gdm-simple-slave.c       |   28 ++++++++++++
 daemon/gdm-slave.c              |   27 ++++++++++++
 daemon/gdm-slave.h              |    1 +
 daemon/gdm-slave.xml            |    3 +
 9 files changed, 236 insertions(+), 18 deletions(-)
---
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 07240e9..2b23492 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -1709,6 +1709,53 @@ gdm_display_start_initial_session_finish (GdmDisplay    *display,
 }
 
 static void
+on_slave_initial_session_reset (GdmDBusSlave *slave,
+                                GAsyncResult *result,
+                                GTask        *task)
+{
+        GError *error = NULL;
+
+        if (!gdm_dbus_slave_call_reset_initial_session_finish (slave, result, &error)) {
+                g_task_return_error (task, error);
+                return;
+        }
+
+        g_debug ("GdmDisplay: slave reset initial session");
+
+        g_task_return_boolean (task, TRUE);
+}
+
+void
+gdm_display_reset_initial_session (GdmDisplay *display,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+        GTask *task;
+
+        task = g_task_new (display, cancellable, callback, user_data);
+
+        gdm_dbus_slave_call_reset_initial_session (display->priv->slave_proxy,
+                                                   cancellable,
+                                                   (GAsyncReadyCallback)
+                                                   on_slave_initial_session_reset,
+                                                   task);
+}
+
+gboolean
+gdm_display_reset_initial_session_finish (GdmDisplay *display,
+                                          GAsyncResult *result,
+                                          GError **error)
+{
+        gboolean outcome;
+
+        outcome = g_task_propagate_boolean (G_TASK (result), error);
+        g_object_unref (G_OBJECT (result));
+
+        return outcome;
+}
+
+static void
 on_slave_initial_session_stopped (GdmDBusSlave *slave,
                                   GAsyncResult *result,
                                   GTask        *task)
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index 391c2dd..ee62020 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -161,6 +161,14 @@ void                gdm_display_start_initial_session           (GdmDisplay *dis
 gboolean            gdm_display_start_initial_session_finish    (GdmDisplay *display,
                                                                  GAsyncResult *result,
                                                                  GError **error);
+void                gdm_display_reset_initial_session           (GdmDisplay *display,
+                                                                 GCancellable *cancellable,
+                                                                 GAsyncReadyCallback callback,
+                                                                 gpointer user_data);
+
+gboolean            gdm_display_reset_initial_session_finish    (GdmDisplay *display,
+                                                                 GAsyncResult *result,
+                                                                 GError **error);
 void                gdm_display_stop_initial_session           (GdmDisplay   *display,
                                                                 const char   *username,
                                                                 GCancellable *cancellable,
diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c
index 932cc06..cdd5fe4 100644
--- a/daemon/gdm-launch-environment.c
+++ b/daemon/gdm-launch-environment.c
@@ -73,6 +73,7 @@ struct GdmLaunchEnvironmentPrivate
         char           *x11_authority_file;
         char           *dbus_session_bus_address;
         gboolean        x11_display_is_local;
+        gboolean        resetting;
 };
 
 enum {
@@ -93,6 +94,7 @@ enum {
 enum {
         OPENED,
         STARTED,
+        RESET,
         STOPPED,
         EXITED,
         DIED,
@@ -329,7 +331,9 @@ on_session_opened (GdmSession           *session,
 {
         launch_environment->priv->session_id = g_strdup (session_id);
 
-        g_signal_emit (G_OBJECT (launch_environment), signals [OPENED], 0);
+        if (!launch_environment->priv->resetting) {
+                g_signal_emit (G_OBJECT (launch_environment), signals [OPENED], 0);
+        }
         gdm_session_start_session (launch_environment->priv->session, service_name);
 }
 
@@ -340,7 +344,12 @@ on_session_started (GdmSession           *session,
                     GdmLaunchEnvironment *launch_environment)
 {
         launch_environment->priv->pid = pid;
-        g_signal_emit (G_OBJECT (launch_environment), signals [STARTED], 0);
+        if (!launch_environment->priv->resetting) {
+                g_signal_emit (G_OBJECT (launch_environment), signals [STARTED], 0);
+        } else {
+                launch_environment->priv->resetting = FALSE;
+                g_signal_emit (G_OBJECT (launch_environment), signals [RESET], 0);
+        }
 }
 
 static void
@@ -348,9 +357,15 @@ on_session_exited (GdmSession           *session,
                    int                   exit_code,
                    GdmLaunchEnvironment *launch_environment)
 {
+        if (session != launch_environment->priv->session) {
+                return;
+        }
+
         gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment");
 
-        g_signal_emit (G_OBJECT (launch_environment), signals [EXITED], 0, exit_code);
+        if (!launch_environment->priv->resetting) {
+                g_signal_emit (G_OBJECT (launch_environment), signals [EXITED], 0, exit_code);
+        }
 }
 
 static void
@@ -358,9 +373,15 @@ on_session_died (GdmSession           *session,
                  int                   signal_number,
                  GdmLaunchEnvironment *launch_environment)
 {
+        if (session != launch_environment->priv->session) {
+                return;
+        }
+
         gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment");
 
-        g_signal_emit (G_OBJECT (launch_environment), signals [DIED], 0, signal_number);
+        if (!launch_environment->priv->resetting) {
+                g_signal_emit (G_OBJECT (launch_environment), signals [DIED], 0, signal_number);
+        }
 }
 
 static void
@@ -396,7 +417,9 @@ on_conversation_stopped (GdmSession           *session,
 
         if (launch_environment->priv->pid > 1) {
                 gdm_signal_pid (-launch_environment->priv->pid, SIGTERM);
-                g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
+                if (!launch_environment->priv->resetting) {
+                        g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
+                }
         }
 
         if (conversation_session != NULL) {
@@ -426,6 +449,23 @@ ensure_directory_with_uid_gid (const char  *path,
         return TRUE;
 }
 
+static void
+start_program (GdmLaunchEnvironment *launch_environment)
+{
+        gdm_session_start_conversation (launch_environment->priv->session, "gdm-launch-environment");
+
+        if (launch_environment->priv->dbus_session_bus_address) {
+                gdm_session_select_program (launch_environment->priv->session, 
launch_environment->priv->command);
+        } else {
+                /* wrap it in dbus-launch */
+                char *command = g_strdup_printf ("%s %s", DBUS_LAUNCH_COMMAND, 
launch_environment->priv->command);
+
+                gdm_session_select_program (launch_environment->priv->session, command);
+                g_free (command);
+        }
+
+}
+
 /**
  * gdm_launch_environment_start:
  * @disp: Pointer to a GdmDisplay structure
@@ -502,18 +542,7 @@ gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment)
                           "session-died",
                           G_CALLBACK (on_session_died),
                           launch_environment);
-
-        gdm_session_start_conversation (launch_environment->priv->session, "gdm-launch-environment");
-
-        if (launch_environment->priv->dbus_session_bus_address) {
-                gdm_session_select_program (launch_environment->priv->session, 
launch_environment->priv->command);
-        } else {
-                /* wrap it in dbus-launch */
-                char *command = g_strdup_printf ("%s %s", DBUS_LAUNCH_COMMAND, 
launch_environment->priv->command);
-
-                gdm_session_select_program (launch_environment->priv->session, command);
-                g_free (command);
-        }
+        start_program (launch_environment);
 
         res = TRUE;
  out:
@@ -525,6 +554,16 @@ gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment)
 }
 
 gboolean
+gdm_launch_environment_reset (GdmLaunchEnvironment *launch_environment)
+{
+        launch_environment->priv->resetting = TRUE;
+        gdm_launch_environment_stop (launch_environment);
+        gdm_launch_environment_start (launch_environment);
+
+        return TRUE;
+}
+
+gboolean
 gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment)
 {
         if (launch_environment->priv->pid > 1) {
@@ -537,7 +576,9 @@ gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment)
                         g_clear_object (&launch_environment->priv->session);
                 }
 
-                g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
+                if (!launch_environment->priv->resetting) {
+                        g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
+                }
         }
 
         return TRUE;
@@ -850,6 +891,16 @@ gdm_launch_environment_class_init (GdmLaunchEnvironmentClass *klass)
                               g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
                               0);
+        signals [RESET] =
+                g_signal_new ("reset",
+                              G_OBJECT_CLASS_TYPE (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (GdmLaunchEnvironmentClass, reset),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
         signals [STOPPED] =
                 g_signal_new ("stopped",
                               G_OBJECT_CLASS_TYPE (object_class),
diff --git a/daemon/gdm-launch-environment.h b/daemon/gdm-launch-environment.h
index 8f27643..2de1e37 100644
--- a/daemon/gdm-launch-environment.h
+++ b/daemon/gdm-launch-environment.h
@@ -54,6 +54,7 @@ typedef struct
         /* signals */
         void (* opened)            (GdmLaunchEnvironment  *launch_environment);
         void (* started)           (GdmLaunchEnvironment  *launch_environment);
+        void (* reset)             (GdmLaunchEnvironment  *launch_environment);
         void (* stopped)           (GdmLaunchEnvironment  *launch_environment);
         void (* exited)            (GdmLaunchEnvironment  *launch_environment,
                                     int                    exit_code);
@@ -64,6 +65,7 @@ typedef struct
 GType                 gdm_launch_environment_get_type           (void);
 
 gboolean              gdm_launch_environment_start              (GdmLaunchEnvironment *launch_environment);
+gboolean              gdm_launch_environment_reset              (GdmLaunchEnvironment *launch_environment);
 gboolean              gdm_launch_environment_stop               (GdmLaunchEnvironment *launch_environment);
 GdmSession *          gdm_launch_environment_get_session        (GdmLaunchEnvironment *launch_environment);
 char *                gdm_launch_environment_get_session_id     (GdmLaunchEnvironment *launch_environment);
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 6624e85..1144f7c 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -105,6 +105,9 @@ static void     gdm_manager_finalize    (GObject         *object);
 static void     on_initial_session_set_up (GdmDisplay   *display,
                                            GAsyncResult *result,
                                            GdmManager   *manager);
+static void on_initial_session_started (GdmDisplay   *display,
+                                        GAsyncResult *result,
+                                        GdmManager   *manager);
 static void create_session_for_display (GdmManager *manager,
                                         GdmDisplay *display,
                                         uid_t       allowed_user);
@@ -820,6 +823,22 @@ start_user_session (GdmManager *manager,
 }
 
 static void
+reset_session (GdmManager *manager,
+               GdmSession *session)
+{
+        GdmDisplay *display;
+        uid_t allowed_uid;
+
+        allowed_uid = gdm_session_get_allowed_user (session);
+
+        display = get_display_for_session (manager, session);
+        g_object_set_data (G_OBJECT (display), "gdm-session", NULL);
+        g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
+
+        create_session_for_display (manager, display, allowed_uid);
+}
+
+static void
 on_initial_session_stopped (GdmDisplay   *display,
                             GAsyncResult *result,
                             StartUserSessionOperation *operation)
@@ -841,10 +860,30 @@ on_initial_session_stopped (GdmDisplay   *display,
         start_user_session (operation->manager, display, operation);
 }
 
+static void
+on_initial_session_reset (GdmDisplay   *display,
+                          GAsyncResult *result)
+{
+        GError *error = NULL;
+        gboolean reset;
+
+        reset = gdm_display_reset_initial_session_finish (display, result, &error);
+
+        if (!reset) {
+                g_warning ("Couldn't reset initial session on display: %s",
+                           error->message);
+                g_error_free (error);
+                gdm_display_unmanage (display);
+                gdm_display_finish (display);
+                return;
+        }
+}
+
 static gboolean
 on_start_user_session (StartUserSessionOperation *operation)
 {
         gboolean migrated;
+        gboolean session_has_own_display_server = FALSE;
         gboolean fail_if_already_switched = TRUE;
 
         g_debug ("GdmManager: start or jump to session");
@@ -863,6 +902,18 @@ on_start_user_session (StartUserSessionOperation *operation)
                    user switching. */
                 gdm_session_reset (operation->session);
                 destroy_start_user_session_operation (operation);
+        } else if (session_has_own_display_server) {
+                GdmDisplay *display;
+
+                g_debug ("GdmManager: session has its display server, reusing our server for another login 
screen");
+                reset_session (operation->manager, operation->session);
+                display = get_display_for_session (operation->manager, operation->session);
+                gdm_display_reset_initial_session (display,
+                                                   NULL,
+                                                   (GAsyncReadyCallback)
+                                                   on_initial_session_reset,
+                                                   NULL);
+                start_user_session (operation->manager, NULL, operation);
         } else {
                 GdmDisplay *display;
                 char *username;
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 749d682..8761c27 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -366,6 +366,19 @@ on_greeter_environment_session_opened (GdmLaunchEnvironment *greeter_environment
 }
 
 static void
+on_greeter_environment_session_reset (GdmLaunchEnvironment *greeter_environment,
+                                      GdmSimpleSlave       *slave)
+{
+        char       *session_id;
+
+        g_debug ("GdmSimpleSlave: Greeter reset");
+        session_id = gdm_launch_environment_get_session_id (GDM_LAUNCH_ENVIRONMENT (greeter_environment));
+
+        g_object_set (GDM_SLAVE (slave), "session-id", session_id, NULL);
+        g_free (session_id);
+}
+
+static void
 on_greeter_environment_session_started (GdmLaunchEnvironment *greeter_environment,
                                         GdmSimpleSlave       *slave)
 {
@@ -613,6 +626,10 @@ start_launch_environment (GdmSimpleSlave *slave,
                           G_CALLBACK (on_greeter_environment_session_opened),
                           slave);
         g_signal_connect (slave->priv->greeter_environment,
+                          "reset",
+                          G_CALLBACK (on_greeter_environment_session_reset),
+                          slave);
+        g_signal_connect (slave->priv->greeter_environment,
                           "started",
                           G_CALLBACK (on_greeter_environment_session_started),
                           slave);
@@ -757,6 +774,16 @@ gdm_simple_slave_start_initial_session (GdmSlave *slave)
         }
 }
 
+static void
+gdm_simple_slave_reset_initial_session (GdmSlave *slave)
+{
+        GdmSimpleSlave *self = GDM_SIMPLE_SLAVE (slave);
+
+        if (self->priv->greeter_environment != NULL) {
+                gdm_launch_environment_reset (GDM_LAUNCH_ENVIRONMENT (self->priv->greeter_environment));
+        }
+}
+
 static gboolean
 idle_connect_to_display (GdmSimpleSlave *slave)
 {
@@ -1024,6 +1051,7 @@ gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass)
         slave_class->stop = gdm_simple_slave_stop;
         slave_class->set_up_initial_session = gdm_simple_slave_set_up_initial_session;
         slave_class->start_initial_session = gdm_simple_slave_start_initial_session;
+        slave_class->reset_initial_session = gdm_simple_slave_reset_initial_session;
         slave_class->stop_initial_session = gdm_simple_slave_stop_initial_session;
 
         g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate));
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 06d857c..de512eb 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -1203,6 +1203,29 @@ handle_start_initial_session (GdmDBusSlave          *skeleton,
 }
 
 static gboolean
+handle_reset_initial_session (GdmDBusSlave          *skeleton,
+                              GDBusMethodInvocation *invocation,
+                              GdmSlave              *slave)
+{
+        GdmSlaveClass *slave_class;
+
+        slave_class = GDM_SLAVE_GET_CLASS (slave);
+        if (slave_class->reset_initial_session == NULL) {
+                g_dbus_method_invocation_return_dbus_error (invocation,
+                                                            "org.gnome.DisplayManager.Slave.Unsupported",
+                                                            "Connections to the slave are not supported by 
this slave");
+                return TRUE;
+        }
+
+        slave_class->reset_initial_session (slave);
+
+        gdm_dbus_slave_complete_reset_initial_session (skeleton, invocation);
+
+        return TRUE;
+}
+
+
+static gboolean
 handle_stop_initial_session (GdmDBusSlave          *skeleton,
                              GDBusMethodInvocation *invocation,
                              const char            *username,
@@ -1251,6 +1274,10 @@ register_slave (GdmSlave *slave)
                           G_CALLBACK (handle_start_initial_session),
                           slave);
         g_signal_connect (slave->priv->skeleton,
+                          "handle-reset-initial-session",
+                          G_CALLBACK (handle_reset_initial_session),
+                          slave);
+        g_signal_connect (slave->priv->skeleton,
                           "handle-stop-initial-session",
                           G_CALLBACK (handle_stop_initial_session),
                           slave);
diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h
index e3264f8..14c9ff7 100644
--- a/daemon/gdm-slave.h
+++ b/daemon/gdm-slave.h
@@ -53,6 +53,7 @@ typedef struct
         void     (* set_up_initial_session) (GdmSlave    *slave,
                                              char       **username);
         void     (* start_initial_session) (GdmSlave  *slave);
+        void     (* reset_initial_session) (GdmSlave  *slave);
         void     (* stop_initial_session) (GdmSlave   *slave,
                                            const char *username);
 
diff --git a/daemon/gdm-slave.xml b/daemon/gdm-slave.xml
index 3f563b4..6e9e2d1 100644
--- a/daemon/gdm-slave.xml
+++ b/daemon/gdm-slave.xml
@@ -11,6 +11,9 @@
     <method name="StartInitialSession">
     </method>
 
+    <method name="ResetInitialSession">
+    </method>
+
     <method name="StopInitialSession">
       <arg name="username" type="s" direction="in" />
     </method>


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