summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2014-02-25 12:23:57 -0500
committerJasper St. Pierre <jstpierre@mecheye.net>2014-03-17 17:01:16 -0400
commita22e5252509332417380aa8169f6f58225cbe502 (patch)
tree1284591e7e9c24ffaaabd78eb327f95e47e27ae9
parent3d7c84b0fe5a5805c8a58350f2517b58972b9844 (diff)
downloadgdm-a22e5252509332417380aa8169f6f58225cbe502.tar.gz
display: Clean up old signal handlers
The signal handlers here are intended to be used if the slave itself tries to stop, for instance if the server or greeter die, and will try to finish the display on its own. Letting the signal handler run again will finish the display *again* after an idle, meaning we have this path: gdm_display_finish gdm_display_unmanage on_server_stopped queue_finish ... idle ... gdm_display_finish gdm_display_unmanage on_server_stopped queue_finish ... This might have been an infinite loop, except for the fact that GDM smartly has code to detect the failure state where the X server starts up and stops sufficiently quickly, and in that case transitions the display to the FAILED state, which causes GdmDisplayStore to unref the last ref on the GdmDisplay. Since the finish is still queued, finish_idle runs, and very quickly discovers that our object is no longer a GdmDisplay, so this very quickly manifests into a: gdm_display_finish: assertion 'GDM_IS_DISPLAY (display)' failed error. Not before poking a hole and corrupting some memory trying to clear the finish_idle_id, however.
-rw-r--r--daemon/gdm-display.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index f966b52a..486d167e 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -686,6 +686,10 @@ gdm_display_real_unmanage (GdmDisplay *display)
g_timer_stop (display->priv->slave_timer);
if (display->priv->slave != NULL) {
+ g_signal_handlers_disconnect_by_func (display->priv->slave,
+ G_CALLBACK (on_slave_started), display);
+ g_signal_handlers_disconnect_by_func (display->priv->slave,
+ G_CALLBACK (on_slave_stopped), display);
gdm_slave_stop (display->priv->slave);
g_object_unref (display->priv->slave);
display->priv->slave = NULL;