diff options
author | William Jon McCann <jmccann@redhat.com> | 2008-02-21 23:08:25 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2008-02-21 23:08:25 +0000 |
commit | 3f2df9aeedb168524317d18bad0ed64c8d06c42b (patch) | |
tree | 9bc37c6409fbe626c4fc4a98365663efb28977a7 /daemon | |
parent | e237bdb9536f5587690885039fba0f22c7678d47 (diff) | |
download | gdm-3f2df9aeedb168524317d18bad0ed64c8d06c42b.tar.gz |
Add quick death and looping detection for displays.
2008-02-21 William Jon McCann <jmccann@redhat.com>
* daemon/gdm-display-store.c: (remove_display),
(gdm_display_store_remove):
* daemon/gdm-display.c: (gdm_display_add_user_authorization),
(gdm_display_set_slave_bus_name),
(gdm_display_remove_user_authorization), (finish_idle),
(slave_exited), (slave_died), (_gdm_display_set_status),
(gdm_display_real_manage), (gdm_display_manage),
(gdm_display_real_finish), (gdm_display_finish),
(gdm_display_real_unmanage), (gdm_display_set_property),
(gdm_display_get_property), (gdm_display_dispose),
(gdm_display_class_init), (gdm_display_init),
(gdm_display_finalize):
* daemon/gdm-display.h:
* daemon/gdm-local-display-factory.c: (take_next_display_number),
(on_display_disposed), (on_static_display_status_changed),
(create_display):
* daemon/gdm-manager.c: (remove_display_for_connection):
* daemon/gdm-static-display.c: (gdm_static_display_finish):
Add quick death and looping detection for displays.
svn path=/trunk/; revision=5838
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/gdm-display-store.c | 15 | ||||
-rw-r--r-- | daemon/gdm-display.c | 97 | ||||
-rw-r--r-- | daemon/gdm-display.h | 7 | ||||
-rw-r--r-- | daemon/gdm-local-display-factory.c | 68 | ||||
-rw-r--r-- | daemon/gdm-manager.c | 3 | ||||
-rw-r--r-- | daemon/gdm-static-display.c | 11 |
6 files changed, 173 insertions, 28 deletions
diff --git a/daemon/gdm-display-store.c b/daemon/gdm-display-store.c index ac3b51d1..62d7e93f 100644 --- a/daemon/gdm-display-store.c +++ b/daemon/gdm-display-store.c @@ -73,13 +73,26 @@ gdm_display_store_clear (GdmDisplayStore *store) g_hash_table_remove_all (store->priv->displays); } +static gboolean +remove_display (char *id, + GdmDisplay *display, + GdmDisplay *display_to_remove) +{ + if (display == display_to_remove) { + return TRUE; + } + return FALSE; +} + gboolean gdm_display_store_remove (GdmDisplayStore *store, GdmDisplay *display) { g_return_val_if_fail (store != NULL, FALSE); - g_warning ("GdmDisplayStore: Implement me"); + gdm_display_store_foreach_remove (store, + (GdmDisplayStoreFunc)remove_display, + display); return FALSE; } diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c index ce1b4823..99a9850a 100644 --- a/daemon/gdm-display.c +++ b/daemon/gdm-display.c @@ -43,7 +43,7 @@ static guint32 display_serial = 1; #define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate)) -#define DEFAULT_SLAVE_COMMAND LIBEXECDIR"/gdm-simple-slave" +#define DEFAULT_SLAVE_COMMAND LIBEXECDIR "/gdm-simple-slave" struct GdmDisplayPrivate { @@ -55,6 +55,7 @@ struct GdmDisplayPrivate char *x11_display_name; int status; time_t creation_time; + GTimer *slave_timer; char *slave_command; char *x11_cookie; @@ -72,6 +73,7 @@ struct GdmDisplayPrivate enum { PROP_0, PROP_ID, + PROP_STATUS, PROP_SEAT_ID, PROP_REMOTE_HOSTNAME, PROP_X11_DISPLAY_NUMBER, @@ -253,7 +255,7 @@ gdm_display_add_user_authorization (GdmDisplay *display, g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("Adding authorization for user:%s on display %s", username, display->priv->x11_display_name); + g_debug ("GdmDisplay: Adding authorization for user:%s on display %s", username, display->priv->x11_display_name); g_object_ref (display); ret = GDM_DISPLAY_GET_CLASS (display)->add_user_authorization (display, username, filename, error); @@ -280,7 +282,7 @@ gdm_display_set_slave_bus_name (GdmDisplay *display, g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("Setting slave bus name:%s on display %s", name, display->priv->x11_display_name); + g_debug ("GdmDisplay: Setting slave bus name:%s on display %s", name, display->priv->x11_display_name); g_object_ref (display); ret = GDM_DISPLAY_GET_CLASS (display)->set_slave_bus_name (display, name, error); @@ -308,7 +310,7 @@ gdm_display_remove_user_authorization (GdmDisplay *display, g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("Removing authorization for user:%s on display %s", username, display->priv->x11_display_name); + g_debug ("GdmDisplay: Removing authorization for user:%s on display %s", username, display->priv->x11_display_name); g_object_ref (display); ret = GDM_DISPLAY_GET_CLASS (display)->remove_user_authorization (display, username, error); @@ -399,8 +401,9 @@ gdm_display_get_seat_id (GdmDisplay *display, static gboolean finish_idle (GdmDisplay *display) { - gdm_display_finish (display); display->priv->finish_idle_id = 0; + /* finish may end up finalizing object */ + gdm_display_finish (display); return FALSE; } @@ -417,7 +420,7 @@ slave_exited (GdmSlaveProxy *proxy, int code, GdmDisplay *display) { - g_debug ("Slave exited: %d", code); + g_debug ("GdmDisplay: Slave exited: %d", code); queue_finish (display); } @@ -427,11 +430,22 @@ slave_died (GdmSlaveProxy *proxy, int signum, GdmDisplay *display) { - g_debug ("Slave died: %d", signum); + g_debug ("GdmDisplay: Slave died: %d", signum); queue_finish (display); } + +static void +_gdm_display_set_status (GdmDisplay *display, + int status) +{ + if (status != display->priv->status) { + display->priv->status = status; + g_object_notify (G_OBJECT (display), "status"); + } +} + static gboolean gdm_display_real_manage (GdmDisplay *display) { @@ -439,7 +453,7 @@ gdm_display_real_manage (GdmDisplay *display) g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("GdmDisplay manage display"); + g_debug ("GdmDisplay: manage display"); g_assert (display->priv->slave_proxy == NULL); @@ -449,7 +463,7 @@ gdm_display_real_manage (GdmDisplay *display) return FALSE; } - display->priv->status = GDM_DISPLAY_MANAGED; + _gdm_display_set_status (display, GDM_DISPLAY_MANAGED); display->priv->slave_proxy = gdm_slave_proxy_new (); g_signal_connect (display->priv->slave_proxy, @@ -468,6 +482,8 @@ gdm_display_real_manage (GdmDisplay *display) gdm_slave_proxy_set_command (display->priv->slave_proxy, command); g_free (command); + g_timer_start (display->priv->slave_timer); + gdm_slave_proxy_start (display->priv->slave_proxy); return TRUE; @@ -480,7 +496,7 @@ gdm_display_manage (GdmDisplay *display) g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("Managing display: %s", display->priv->id); + g_debug ("GdmDisplay: Managing display: %s", display->priv->id); g_object_ref (display); ret = GDM_DISPLAY_GET_CLASS (display)->manage (display); @@ -494,9 +510,9 @@ gdm_display_real_finish (GdmDisplay *display) { g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - display->priv->status = GDM_DISPLAY_FINISHED; + _gdm_display_set_status (display, GDM_DISPLAY_FINISHED); - g_debug ("GdmDisplay finish display"); + g_debug ("GdmDisplay: finish display"); return TRUE; } @@ -508,7 +524,7 @@ gdm_display_finish (GdmDisplay *display) g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - g_debug ("Finishing display: %s", display->priv->id); + g_debug ("GdmDisplay: Finishing display: %s", display->priv->id); g_object_ref (display); ret = GDM_DISPLAY_GET_CLASS (display)->finish (display); @@ -520,12 +536,14 @@ gdm_display_finish (GdmDisplay *display) static gboolean gdm_display_real_unmanage (GdmDisplay *display) { - g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + gdouble elapsed; - display->priv->status = GDM_DISPLAY_UNMANAGED; + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); g_debug ("GdmDisplay: unmanage display"); + g_timer_stop (display->priv->slave_timer); + if (display->priv->slave_proxy != NULL) { gdm_slave_proxy_stop (display->priv->slave_proxy); @@ -545,6 +563,14 @@ gdm_display_real_unmanage (GdmDisplay *display) display->priv->access_file = NULL; } + elapsed = g_timer_elapsed (display->priv->slave_timer, NULL); + if (elapsed < 10) { + g_warning ("GdmDisplay: display lasted %lf seconds", elapsed); + _gdm_display_set_status (display, GDM_DISPLAY_FAILED); + } else { + _gdm_display_set_status (display, GDM_DISPLAY_UNMANAGED); + } + return TRUE; } @@ -682,6 +708,9 @@ gdm_display_set_property (GObject *object, case PROP_ID: _gdm_display_set_id (self, g_value_get_string (value)); break; + case PROP_STATUS: + _gdm_display_set_status (self, g_value_get_int (value)); + break; case PROP_SEAT_ID: _gdm_display_set_seat_id (self, g_value_get_string (value)); break; @@ -723,6 +752,9 @@ gdm_display_get_property (GObject *object, case PROP_ID: g_value_set_string (value, self->priv->id); break; + case PROP_STATUS: + g_value_set_int (value, self->priv->status); + break; case PROP_SEAT_ID: g_value_set_string (value, self->priv->seat_id); break; @@ -807,13 +839,29 @@ gdm_display_dispose (GObject *object) display = GDM_DISPLAY (object); + g_debug ("GdmDisplay: Disposing display"); + if (display->priv->finish_idle_id > 0) { g_source_remove (display->priv->finish_idle_id); display->priv->finish_idle_id = 0; } - g_debug ("GdmDisplay: Disposing display"); - gdm_display_unmanage (display); + if (display->priv->slave_proxy != NULL) { + g_object_unref (display->priv->slave_proxy); + display->priv->slave_proxy = NULL; + } + + if (display->priv->user_access_file != NULL) { + gdm_display_access_file_close (display->priv->user_access_file); + g_object_unref (display->priv->user_access_file); + display->priv->user_access_file = NULL; + } + + if (display->priv->access_file != NULL) { + gdm_display_access_file_close (display->priv->access_file); + g_object_unref (display->priv->access_file); + display->priv->access_file = NULL; + } G_OBJECT_CLASS (gdm_display_parent_class)->dispose (object); } @@ -904,6 +952,15 @@ gdm_display_class_init (GdmDisplayClass *klass) "slave command", DEFAULT_SLAVE_COMMAND, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, + PROP_STATUS, + g_param_spec_int ("status", + "status", + "status", + -1, + G_MAXINT, + GDM_DISPLAY_UNMANAGED, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_type_class_add_private (klass, sizeof (GdmDisplayPrivate)); @@ -916,8 +973,8 @@ gdm_display_init (GdmDisplay *display) display->priv = GDM_DISPLAY_GET_PRIVATE (display); - display->priv->status = GDM_DISPLAY_UNMANAGED; display->priv->creation_time = time (NULL); + display->priv->slave_timer = g_timer_new (); } static void @@ -948,5 +1005,9 @@ gdm_display_finalize (GObject *object) g_object_unref (display->priv->user_access_file); } + if (display->priv->slave_timer != NULL) { + g_timer_destroy (display->priv->slave_timer); + } + G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object); } diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h index 87e274bc..cfdb6564 100644 --- a/daemon/gdm-display.h +++ b/daemon/gdm-display.h @@ -37,14 +37,15 @@ G_BEGIN_DECLS typedef struct GdmDisplayPrivate GdmDisplayPrivate; typedef enum { - GDM_DISPLAY_UNMANAGED, + GDM_DISPLAY_UNMANAGED = 0, GDM_DISPLAY_MANAGED, - GDM_DISPLAY_FINISHED + GDM_DISPLAY_FINISHED, + GDM_DISPLAY_FAILED, } GdmDisplayStatus; typedef struct { - GObject parent; + GObject parent; GdmDisplayPrivate *priv; } GdmDisplay; diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 6c2aee6f..40c6aab3 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -51,11 +51,16 @@ #define HAL_DBUS_DEVICE_INTERFACE "org.freedesktop.Hal.Device" #define SEAT_PCI_DEVICE_CLASS 3 +#define MAX_DISPLAY_FAILURES 5 + struct GdmLocalDisplayFactoryPrivate { DBusGConnection *connection; DBusGProxy *proxy; GHashTable *displays; + + /* FIXME: this needs to be per seat? */ + guint num_failures; }; enum { @@ -66,6 +71,8 @@ static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryC static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory); static void gdm_local_display_factory_finalize (GObject *object); +static GdmDisplay *create_display (GdmLocalDisplayFactory *factory); + static gpointer local_display_factory_object = NULL; G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY) @@ -128,7 +135,7 @@ take_next_display_number (GdmLocalDisplayFactory *factory) g_debug ("GdmLocalDisplayFactory: Found the following X displays:"); for (l = list; l != NULL; l = l->next) { - g_debug ("%u", GPOINTER_TO_UINT (l->data)); + g_debug ("GdmLocalDisplayFactory: %u", GPOINTER_TO_UINT (l->data)); } for (l = list; l != NULL; l = l->next) { @@ -159,8 +166,7 @@ static void on_display_disposed (GdmLocalDisplayFactory *factory, GdmDisplay *display) { - /* remove the display number from accounting */ - + g_debug ("GdmLocalDisplayFactory: Display %p disposed", display); } static void @@ -275,6 +281,57 @@ gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factor return ret; } +static void +on_static_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory) +{ + int status; + GdmDisplayStore *store; + int num; + + num = -1; + gdm_display_get_x11_display_number (display, &num, NULL); + g_assert (num != -1); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + + status = gdm_display_get_status (display); + + g_debug ("GdmLocalDisplayFactory: static display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + /* remove the display number from factory->priv->displays + so that it may be reused */ + g_hash_table_remove (factory->priv->displays, GUINT_TO_POINTER (num)); + gdm_display_store_remove (store, display); + /* reset num failures */ + factory->priv->num_failures = 0; + create_display (factory); + break; + case GDM_DISPLAY_FAILED: + /* leave the display number in factory->priv->displays + so that it doesn't get reused */ + gdm_display_store_remove (store, display); + factory->priv->num_failures++; + if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) { + /* oh shit */ + g_critical ("GdmLocalDisplayFactory: maximum number of displays failures reached: check Xorg.log for errors"); + exit (1); + } + + create_display (factory); + break; + case GDM_DISPLAY_UNMANAGED: + break; + case GDM_DISPLAY_MANAGED: + break; + default: + g_assert_not_reached (); + break; + } +} + static GdmDisplay * create_display (GdmLocalDisplayFactory *factory) { @@ -296,6 +353,11 @@ create_display (GdmLocalDisplayFactory *factory) /* FIXME: don't hardcode seat1? */ g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL); + g_signal_connect (display, + "notify::status", + G_CALLBACK (on_static_display_status_changed), + factory); + store_display (factory, num, display); /* let store own the ref */ diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 85c68d89..b0c2a642 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -180,7 +180,8 @@ typedef struct { } RemoveDisplayData; static gboolean -remove_display_for_connection (GdmDisplay *display, +remove_display_for_connection (char *id, + GdmDisplay *display, RemoveDisplayData *data) { g_assert (display != NULL); diff --git a/daemon/gdm-static-display.c b/daemon/gdm-static-display.c index 02f94c0e..07e359c6 100644 --- a/daemon/gdm-static-display.c +++ b/daemon/gdm-static-display.c @@ -98,13 +98,20 @@ gdm_static_display_manage (GdmDisplay *display) static gboolean gdm_static_display_finish (GdmDisplay *display) { + int status; + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); - GDM_DISPLAY_CLASS (gdm_static_display_parent_class)->finish (display); + /* Don't call parent's finish since we don't ever + want to be put in the FINISHED state */ /* restart static displays */ gdm_display_unmanage (display); - gdm_display_manage (display); + + status = gdm_display_get_status (display); + if (status != GDM_DISPLAY_FAILED) { + gdm_display_manage (display); + } return TRUE; } |