[gdm/x-gdm-sessionregisters] Allow sessions to register with GDM
- From: Iain Lane <iainl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm/x-gdm-sessionregisters] Allow sessions to register with GDM
- Date: Tue, 7 May 2019 11:33:44 +0000 (UTC)
commit 3f4f95dae8c3afbc35cec47f93f3a5dc14e1d1be
Author: Iain Lane <iainl gnome org>
Date: Tue May 7 12:21:27 2019 +0100
Allow sessions to register with GDM
Recording when sessions start, for Wayland → Xorg fallback or
transitioning to the user session, is currently done with timeouts.
This isn't ideal, because on some very slow machines the timeout can be
hit before the session has had a chance to fail: if gnome-session takes
more than 3 seconds to fail then the session will be considered to have
exited rather than failed, and so we don't do Xorg fallback.
We can do this more reliably if we allow sessions to optionally register
themselves with GDM. Then we will know when they've started, so can shut
down the greeter or fall back to Xorg as appropriate. The mechanism is
that they specify X-GDM-SessionRegisters=true in their file, and then
call RegsterSession on the DisplayManager interface on the bus to say
that they've started up. If X-GDM-SessionRegisters is missing or false,
GDM will call the same method for them after 10 seconds.
Closes: #483
common/gdm-common.h | 2 +
daemon/gdm-display.c | 46 ++++++++++------
daemon/gdm-local-display-factory.c | 109 +++++++++++++++++++++++++++++++------
daemon/gdm-manager.c | 30 ++++++++++
daemon/gdm-manager.xml | 3 +
daemon/gdm-session.c | 47 ++++++++++++++--
daemon/gdm-session.h | 1 +
daemon/gdm-wayland-session.c | 74 +++++++++++++++++++------
daemon/gdm-x-session.c | 74 +++++++++++++++++++------
9 files changed, 313 insertions(+), 73 deletions(-)
---
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 07812b10..58814aa2 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -27,6 +27,8 @@
#include <pwd.h>
#include <errno.h>
+#define REGISTER_SESSION_TIMEOUT 10
+
#define VE_IGNORE_EINTR(expr) \
do { \
errno = 0; \
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index a8747785..6aaaba4b 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -66,7 +66,6 @@ typedef struct _GdmDisplayPrivate
char *x11_display_name;
int status;
time_t creation_time;
- GTimer *server_timer;
char *x11_cookie;
gsize x11_cookie_size;
@@ -93,6 +92,7 @@ typedef struct _GdmDisplayPrivate
guint allow_timed_login : 1;
guint have_existing_user_accounts : 1;
guint doing_initial_setup : 1;
+ guint registered : 1;
} GdmDisplayPrivate;
enum {
@@ -115,6 +115,7 @@ enum {
PROP_ALLOW_TIMED_LOGIN,
PROP_HAVE_EXISTING_USER_ACCOUNTS,
PROP_DOING_INITIAL_SETUP,
+ PROP_REGISTERED,
};
static void gdm_display_class_init (GdmDisplayClass *klass);
@@ -598,8 +599,6 @@ gdm_display_manage (GdmDisplay *self)
}
}
- g_timer_start (priv->server_timer);
-
if (g_strcmp0 (priv->session_class, "greeter") == 0) {
if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
GDM_DISPLAY_GET_CLASS (self)->manage (self);
@@ -671,7 +670,6 @@ gboolean
gdm_display_unmanage (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
- gdouble elapsed;
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
@@ -681,8 +679,6 @@ gdm_display_unmanage (GdmDisplay *self)
gdm_display_disconnect (self);
- g_timer_stop (priv->server_timer);
-
if (priv->user_access_file != NULL) {
gdm_display_access_file_close (priv->user_access_file);
g_object_unref (priv->user_access_file);
@@ -695,9 +691,8 @@ gdm_display_unmanage (GdmDisplay *self)
priv->access_file = NULL;
}
- elapsed = g_timer_elapsed (priv->server_timer, NULL);
- if (elapsed < 3) {
- g_warning ("GdmDisplay: display lasted %lf seconds", elapsed);
+ if (!priv->registered) {
+ g_warning ("GdmDisplay: Session never registered, failing");
_gdm_display_set_status (self, GDM_DISPLAY_FAILED);
} else {
_gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
@@ -871,6 +866,17 @@ _gdm_display_set_is_local (GdmDisplay *self,
priv->is_local = is_local;
}
+static void
+_gdm_display_set_registered (GdmDisplay *self,
+ gboolean registered)
+{
+ GdmDisplayPrivate *priv;
+
+ priv = gdm_display_get_instance_private (self);
+ g_debug ("GdmDisplay: registered: %s", registered? "yes" : "no");
+ priv->registered = registered;
+}
+
static void
_gdm_display_set_launch_environment (GdmDisplay *self,
GdmLaunchEnvironment *launch_environment)
@@ -959,6 +965,9 @@ gdm_display_set_property (GObject *object,
case PROP_IS_INITIAL:
_gdm_display_set_is_initial (self, g_value_get_boolean (value));
break;
+ case PROP_REGISTERED:
+ _gdm_display_set_registered (self, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1031,6 +1040,9 @@ gdm_display_get_property (GObject *object,
case PROP_DOING_INITIAL_SETUP:
g_value_set_boolean (value, priv->doing_initial_setup);
break;
+ case PROP_REGISTERED:
+ g_value_set_boolean (value, priv->registered);
+ break;
case PROP_ALLOW_TIMED_LOGIN:
g_value_set_boolean (value, priv->allow_timed_login);
break;
@@ -1355,6 +1367,14 @@ gdm_display_class_init (GdmDisplayClass *klass)
NULL,
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class,
+ PROP_REGISTERED,
+ g_param_spec_boolean ("registered",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (object_class,
PROP_LAUNCH_ENVIRONMENT,
g_param_spec_object ("launch-environment",
@@ -1381,7 +1401,6 @@ gdm_display_init (GdmDisplay *self)
priv = gdm_display_get_instance_private (self);
priv->creation_time = time (NULL);
- priv->server_timer = g_timer_new ();
}
static void
@@ -1419,10 +1438,6 @@ gdm_display_finalize (GObject *object)
g_object_unref (priv->user_access_file);
}
- if (priv->server_timer != NULL) {
- g_timer_destroy (priv->server_timer);
- }
-
G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
}
@@ -1659,7 +1674,7 @@ gdm_display_start_greeter_session (GdmDisplay *self)
priv = gdm_display_get_instance_private (self);
g_return_if_fail (g_strcmp0 (priv->session_class, "greeter") == 0);
- g_debug ("GdmDisplay: Running greeter");
+ g_debug ("GdmDisplay: Running greeter", self);
display_name = NULL;
seat_id = NULL;
@@ -1720,7 +1735,6 @@ void
gdm_display_stop_greeter_session (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
- GError *error = NULL;
priv = gdm_display_get_instance_private (self);
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 98daca48..6a6897cf 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -28,6 +28,9 @@
#include <glib-object.h>
#include <gio/gio.h>
+#include <linux/vt.h>
+#include <sys/ioctl.h>
+
#include <systemd/sd-login.h>
#include "gdm-common.h"
@@ -66,7 +69,7 @@ struct _GdmLocalDisplayFactory
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
char *tty_of_active_vt;
guint active_vt_watch_id;
- guint wait_to_finish_timeout_id;
+ guint wait_to_register_id;
#endif
};
@@ -605,19 +608,58 @@ lookup_by_session_id (const char *id,
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
-wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
+lookup_by_vt (const char *id,
+ GdmDisplay *display,
+ gpointer user_data)
+{
+ unsigned int vt_to_find = *(unsigned int *) user_data;
+ unsigned int vt;
+ int ret;
+ const char *display_session_id;
+
+ display_session_id = gdm_display_get_session_id (display);
+
+ ret = sd_session_get_vt (display_session_id, &vt);
+
+ if (ret < 0) {
+ g_debug ("Couldn't look up session %s: %s",
+ display_session_id,
+ strerror (-ret));
+ return FALSE;
+ }
+
+ return (vt_to_find == vt);
+}
+
+static void
+on_display_registered_cb (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
{
+ GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
+ gboolean registered;
+
+ g_object_get (factory, "registered", ®istered, NULL);
+
+ if (!registered)
+ return;
+
+ g_debug ("GdmLocalDisplayFactory: display registered, killing login screen");
+
finish_waiting_displays_on_seat (factory, "seat0");
- factory->wait_to_finish_timeout_id = 0;
- return G_SOURCE_REMOVE;
+
+ g_signal_handler_disconnect (factory, factory->wait_to_register_id);
+ factory->wait_to_register_id = 0;
}
static void
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
- GdmDisplay *display)
+ GdmDisplay *display,
+ GdmDisplay *new_display)
{
g_autofree char *display_session_type = NULL;
gboolean doing_initial_setup = FALSE;
+ gboolean registered;
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
@@ -642,17 +684,36 @@ maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
return;
}
+ g_debug ("GdmLocalDisplayFactory: old display: %p, new display: %p",
+ display,
+ new_display);
+
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
+
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
- /* We stop the greeter after a timeout to avoid flicker */
- if (factory->wait_to_finish_timeout_id != 0)
- g_source_remove (factory->wait_to_finish_timeout_id);
+ /* We stop the greeter once the new session has started fully, when it
+ * registers with us */
+ g_object_get (G_OBJECT (new_display),
+ "registered", ®istered,
+ NULL);
+
+ if (registered) {
+ g_debug ("GdmLocalDisplayFactory: new display already registered, killing greeter");
+ finish_waiting_displays_on_seat (factory, "seat0");
+ return;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: new display not yet registered, waiting to kill greeter");
- factory->wait_to_finish_timeout_id =
- g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
- (GSourceFunc)wait_to_finish_timeout,
- factory);
+ if (factory->wait_to_register_id != 0)
+ g_source_remove (factory->wait_to_register_id);
+
+ factory->wait_to_register_id = g_signal_connect_object (new_display,
+ "notify::registered",
+ G_CALLBACK (on_display_registered_cb),
+ factory,
+ 0);
}
static gboolean
@@ -666,6 +727,9 @@ on_vt_changed (GIOChannel *source,
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
+ struct vt_stat vt_state = { 0 };
+ int current_tty_fd;
+ unsigned int new_vt;
const char *session_type = NULL;
int ret;
@@ -719,6 +783,17 @@ on_vt_changed (GIOChannel *source,
return G_SOURCE_CONTINUE;
}
+ current_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
+
+ if (current_tty_fd < 0) {
+ g_debug ("GdmLocalDisplayFactory: couldn't get current tty: %m");
+ } else if (ioctl (current_tty_fd, VT_GETSTATE, &vt_state) < 0) {
+ g_debug ("GdmLocalDisplayFactory: couldn't get current VT: %m");
+ } else {
+ new_vt = vt_state.v_active;
+ close (current_tty_fd);
+ }
+
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
tty_of_previous_vt, factory->tty_of_active_vt);
@@ -737,6 +812,7 @@ on_vt_changed (GIOChannel *source,
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
+ GdmDisplay *new_display = NULL;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
@@ -744,9 +820,12 @@ on_vt_changed (GIOChannel *source,
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
+ new_display = gdm_display_store_find (store,
+ lookup_by_vt,
+ (gpointer) &new_vt);
if (display != NULL)
- maybe_stop_greeter_in_background (factory, display);
+ maybe_stop_greeter_in_background (factory, display, new_display);
} else {
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
@@ -827,10 +906,6 @@ gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
factory->seat_removed_id = 0;
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
- if (factory->wait_to_finish_timeout_id != 0) {
- g_source_remove (factory->wait_to_finish_timeout_id);
- factory->wait_to_finish_timeout_id = 0;
- }
if (factory->active_vt_watch_id) {
g_source_remove (factory->active_vt_watch_id);
factory->active_vt_watch_id = 0;
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 980aa62d..8e5eacb0 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -803,6 +803,35 @@ gdm_manager_handle_register_display (GdmDBusManager *manager,
return TRUE;
}
+static gboolean
+gdm_manager_handle_register_session (GdmDBusManager *manager,
+ GDBusMethodInvocation *invocation,
+ GVariant *details)
+{
+ GdmManager *self = GDM_MANAGER (manager);
+ GdmDisplay *display;
+ const char *sender;
+ GDBusConnection *connection;
+
+ sender = g_dbus_method_invocation_get_sender (invocation);
+ connection = g_dbus_method_invocation_get_connection (invocation);
+
+ get_display_and_details_for_bus_sender (self, connection, sender, &display,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ g_debug ("GdmManager: trying to register new session on display %p", display);
+
+ if (display != NULL)
+ g_object_set (G_OBJECT (display), "registered", TRUE, NULL);
+ else
+ g_debug ("GdmManager: No display, not registering");
+
+ gdm_dbus_manager_complete_register_session (GDM_DBUS_MANAGER (manager),
+ invocation);
+
+ return TRUE;
+}
+
static gboolean
gdm_manager_handle_open_session (GdmDBusManager *manager,
GDBusMethodInvocation *invocation)
@@ -1159,6 +1188,7 @@ static void
manager_interface_init (GdmDBusManagerIface *interface)
{
interface->handle_register_display = gdm_manager_handle_register_display;
+ interface->handle_register_session = gdm_manager_handle_register_session;
interface->handle_open_session = gdm_manager_handle_open_session;
interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel;
}
diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml
index f11f3fb7..92ef1d02 100644
--- a/daemon/gdm-manager.xml
+++ b/daemon/gdm-manager.xml
@@ -4,6 +4,9 @@
<method name="RegisterDisplay">
<arg name="details" direction="in" type="a{ss}"/>
</method>
+ <method name="RegisterSession">
+ <arg name="details" direction="in" type="a{sv}"/>
+ </method>
<method name="OpenSession">
<arg name="address" direction="out" type="s"/>
</method>
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 6a116a85..0105eac1 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2837,6 +2837,7 @@ gdm_session_start_session (GdmSession *self,
gboolean allow_remote_connections = FALSE;
char *command;
char *program;
+ char *register_session;
g_return_if_fail (GDM_IS_SESSION (self));
g_return_if_fail (self->session_conversation == NULL);
@@ -2862,6 +2863,8 @@ gdm_session_start_session (GdmSession *self,
run_launcher = TRUE;
}
+ register_session = !gdm_session_session_registers (self) ? "--register-session " : "";
+
if (self->selected_program == NULL) {
gboolean run_xsession_script;
@@ -2879,12 +2882,14 @@ gdm_session_start_session (GdmSession *self,
if (run_launcher) {
if (is_x11) {
- program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s %s\"%s\"",
+ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"",
+ register_session,
run_xsession_script? "--run-script " : "",
allow_remote_connections?
"--allow-remote-connections " : "",
command);
} else {
- program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
+ program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
+ register_session,
command);
}
} else if (run_xsession_script) {
@@ -2897,10 +2902,12 @@ gdm_session_start_session (GdmSession *self,
} else {
if (run_launcher) {
if (is_x11) {
- program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"",
+ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"%s\"",
+ register_session,
self->selected_program);
} else {
- program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
+ program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
+ register_session,
self->selected_program);
}
} else {
@@ -3177,6 +3184,38 @@ update_session_type (GdmSession *self)
#endif
}
+gboolean
+gdm_session_session_registers (GdmSession *self)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GKeyFile) key_file = NULL;
+ gboolean session_registers = FALSE;
+ g_autofree char *filename = NULL;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
+ filename = get_session_filename (self);
+
+ key_file = load_key_file_for_file (self, filename, NULL);
+
+ session_registers = g_key_file_get_boolean (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ "X-GDM-SessionRegisters",
+ &error);
+ if (!session_registers &&
+ error != NULL &&
+ !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
+ g_warning ("GdmSession: Couldn't read session file '%s'", filename);
+ return FALSE;
+ }
+
+ g_debug ("GdmSession: '%s' %s self", filename,
+ session_registers ? "registers" : "does not register");
+
+ return session_registers;
+}
+
gboolean
gdm_session_bypasses_xsession (GdmSession *self)
{
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 98acb4f6..3b64ecd2 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -76,6 +76,7 @@ const char *gdm_session_get_display_device (GdmSession *sessi
const char *gdm_session_get_display_seat_id (GdmSession *session);
const char *gdm_session_get_session_id (GdmSession *session);
gboolean gdm_session_bypasses_xsession (GdmSession *session);
+gboolean gdm_session_session_registers (GdmSession *session);
GdmSessionDisplayMode gdm_session_get_display_mode (GdmSession *session);
#ifdef ENABLE_WAYLAND_SUPPORT
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
index 94f49e19..d02c6389 100644
--- a/daemon/gdm-wayland-session.c
+++ b/daemon/gdm-wayland-session.c
@@ -45,6 +45,7 @@ typedef struct
GSubprocess *bus_subprocess;
GDBusConnection *bus_connection;
+ GdmDBusManager *display_manager_proxy;
char *bus_address;
char **environment;
@@ -53,6 +54,8 @@ typedef struct
char *session_command;
int session_exit_status;
+ guint register_session_id;
+
GMainLoop *main_loop;
guint32 debug_enabled : 1;
@@ -385,29 +388,14 @@ static gboolean
register_display (State *state,
GCancellable *cancellable)
{
- GdmDBusManager *manager = NULL;
GError *error = NULL;
gboolean registered = FALSE;
GVariantBuilder details;
- manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
- "org.gnome.DisplayManager",
- "/org/gnome/DisplayManager/Manager",
- cancellable,
- &error);
-
- if (!manager) {
- g_debug ("could not contact display manager: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
g_variant_builder_add (&details, "{ss}", "session-type", "wayland");
- registered = gdm_dbus_manager_call_register_display_sync (manager,
+ registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
g_variant_builder_end (&details),
cancellable,
&error);
@@ -416,8 +404,6 @@ register_display (State *state,
g_error_free (error);
}
-out:
- g_clear_object (&manager);
return registered;
}
@@ -439,6 +425,10 @@ clear_state (State **out_state)
g_clear_object (&state->session_subprocess);
g_clear_pointer (&state->environment, g_strfreev);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
+ if (state->register_session_id > 0) {
+ g_source_remove (state->register_session_id);
+ state->register_session_id = 0;
+ }
*out_state = NULL;
}
@@ -454,6 +444,27 @@ on_sigterm (State *state)
return G_SOURCE_CONTINUE;
}
+static gboolean
+register_session_timeout_cb (gpointer user_data)
+{
+ State *state;
+ GError *error = NULL;
+
+ state = (State *) user_data;
+
+ gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
+ g_variant_new ("a{sv}", NULL),
+ state->cancellable,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Could not register session: %s", error->message);
+ g_error_free (error);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
int
main (int argc,
char **argv)
@@ -464,7 +475,11 @@ main (int argc,
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
+ static gboolean register_session = FALSE;
+ GError *error = NULL;
+
static GOptionEntry entries [] = {
+ { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a
delay", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
@@ -528,6 +543,20 @@ main (int argc,
goto out;
}
+ state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ "org.gnome.DisplayManager",
+ "/org/gnome/DisplayManager/Manager",
+ state->cancellable,
+ &error);
+
+ if (state->display_manager_proxy == NULL) {
+ g_debug ("could not contact display manager: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
ret = register_display (state, state->cancellable);
if (!ret) {
@@ -536,6 +565,15 @@ main (int argc,
goto out;
}
+ if (register_session) {
+ g_debug ("gdm-wayland-session: Will register session in %d seconds",
REGISTER_SESSION_TIMEOUT);
+ state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
+ register_session_timeout_cb,
+ state);
+ } else {
+ g_debug ("gdm-wayland-session: Session will register itself");
+ }
+
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 3b2fcef4..289581cc 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -51,6 +51,7 @@ typedef struct
GSubprocess *bus_subprocess;
GDBusConnection *bus_connection;
+ GdmDBusManager *display_manager_proxy;
char *bus_address;
char **environment;
@@ -59,6 +60,8 @@ typedef struct
char *session_command;
int session_exit_status;
+ guint register_session_id;
+
GMainLoop *main_loop;
guint32 debug_enabled : 1;
@@ -737,30 +740,15 @@ static gboolean
register_display (State *state,
GCancellable *cancellable)
{
- GdmDBusManager *manager = NULL;
GError *error = NULL;
gboolean registered = FALSE;
GVariantBuilder details;
- manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
- "org.gnome.DisplayManager",
- "/org/gnome/DisplayManager/Manager",
- cancellable,
- &error);
-
- if (!manager) {
- g_debug ("could not contact display manager: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
g_variant_builder_add (&details, "{ss}", "session-type", "x11");
g_variant_builder_add (&details, "{ss}", "x11-display-name", state->display_name);
- registered = gdm_dbus_manager_call_register_display_sync (manager,
+ registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
g_variant_builder_end (&details),
cancellable,
&error);
@@ -769,8 +757,6 @@ register_display (State *state,
g_error_free (error);
}
-out:
- g_clear_object (&manager);
return registered;
}
@@ -795,6 +781,10 @@ clear_state (State **out_state)
g_clear_pointer (&state->auth_file, g_free);
g_clear_pointer (&state->display_name, g_free);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
+ if (state->register_session_id > 0) {
+ g_source_remove (state->register_session_id);
+ state->register_session_id = 0;
+ }
*out_state = NULL;
}
@@ -810,6 +800,27 @@ on_sigterm (State *state)
return G_SOURCE_CONTINUE;
}
+static gboolean
+register_session_timeout_cb (gpointer user_data)
+{
+ State *state;
+ GError *error = NULL;
+
+ state = (State *) user_data;
+
+ gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
+ g_variant_new ("a{sv}", NULL),
+ state->cancellable,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Could not register session: %s", error->message);
+ g_error_free (error);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
int
main (int argc,
char **argv)
@@ -822,9 +833,13 @@ main (int argc,
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
+ static gboolean register_session = FALSE;
+ GError *error = NULL;
+
static GOptionEntry entries [] = {
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through
/etc/gdm/Xsession wrapper script"), NULL },
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections,
N_("Listen on TCP socket"), NULL },
+ { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a
delay", NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
@@ -896,6 +911,20 @@ main (int argc,
goto out;
}
+ state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ "org.gnome.DisplayManager",
+ "/org/gnome/DisplayManager/Manager",
+ state->cancellable,
+ &error);
+
+ if (state->display_manager_proxy == NULL) {
+ g_debug ("could not contact display manager: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
ret = register_display (state, state->cancellable);
if (!ret) {
@@ -912,6 +941,15 @@ main (int argc,
goto out;
}
+ if (register_session) {
+ g_debug ("gdm-x-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
+ state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
+ register_session_timeout_cb,
+ state);
+ } else {
+ g_debug ("gdm-x-session: Session will register itself");
+ }
+
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]