[gdm/wip/wayland-for-merge: 11/20] display: Clean up old signal handlers



commit 1003554f097357e522a0eebeab6fe8d5fac2540b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Feb 25 12:23:57 2014 -0500

    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.

 daemon/gdm-display.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
---
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index c904a59..aa9f7b2 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -683,6 +683,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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]