summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--daemon/gdm-display-store.c15
-rw-r--r--daemon/gdm-display.c97
-rw-r--r--daemon/gdm-display.h7
-rw-r--r--daemon/gdm-local-display-factory.c68
-rw-r--r--daemon/gdm-manager.c3
-rw-r--r--daemon/gdm-static-display.c11
7 files changed, 195 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 62f91480..ab686af5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+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.
+
2008-02-21 Ray Strode <rstrode@redhat.com>
* daemon/gdm-session-worker.c:
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;
}