Commit 3f2df9ae authored by William Jon McCann's avatar William Jon McCann Committed by William Jon McCann

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
parent e237bdb9
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:
......
......@@ -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;
}
......
......@@ -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);
}
......@@ -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;
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment