[gdm/wip/wayland-rebase: 7/8] slave: add ability to reset launch environment
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm/wip/wayland-rebase: 7/8] slave: add ability to reset launch environment
- Date: Mon, 10 Feb 2014 20:22:38 +0000 (UTC)
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]