[gnome-online-accounts/gnome-3-8] goaidentity: Fix deadlock in goaalarm on_cancelled



commit 88eecb0f1ae8510d569ece56090bcebc5ab65cf7
Author: Alban Browaeys <prahal yahoo com>
Date:   Sat Aug 3 12:34:07 2013 +0200

    goaidentity: Fix deadlock in goaalarm on_cancelled
    
    Calling g_cancellable_disconnect in a cancelled handler causes a
    deadlock. This happens here as in clear_scheduled_timer_wakeups we
    destroy the cancellable source that emitted the cancelled signal.
    (goaalarm: on_cancelled-> clear_scheduled_wakeups
    -> clear_scheduled_timer_wakeups -> g_source_destroy
    -> g_source_destroy_internal -> g_child_source_remove_internal
    -> g_source_unref_internal -> cancellable_source_finalize
    -> g_cancellable_disconnect).
    
    Thus based on Matthew Barnes , evolution commit
    c155b170bcf644ab2cdf7b11afdda0d9c100772e :
    EPhotoCache: Fix deadlock when cancelling subtasks.
    
    That is, we move the cancelled task into the main thread in an idle
    source, to prevent the disconnect from happening inside the cancelled
    handler.
    
    Fixes: https://bugzilla.gnome.org/705395

 src/goaidentity/goaalarm.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)
---
diff --git a/src/goaidentity/goaalarm.c b/src/goaidentity/goaalarm.c
index c8992cd..9ccb3b6 100644
--- a/src/goaidentity/goaalarm.c
+++ b/src/goaidentity/goaalarm.c
@@ -256,12 +256,31 @@ goa_alarm_init (GoaAlarm *self)
   g_rec_mutex_init (&self->priv->lock);
 }
 
+static gboolean
+async_alarm_cancel_idle_cb (gpointer user_data)
+{
+  GoaAlarm *self = user_data;
+
+  clear_scheduled_wakeups (self);
+  return G_SOURCE_REMOVE;
+}
+
 static void
 on_cancelled (GCancellable *cancellable, gpointer user_data)
 {
   GoaAlarm *self = GOA_ALARM (user_data);
+  GMainContext *main_context;
+  GSource *idle_source;
 
-  clear_scheduled_wakeups (self);
+  main_context = g_main_context_ref_thread_default ();
+
+  idle_source = g_idle_source_new ();
+  g_source_set_priority (idle_source, G_PRIORITY_HIGH_IDLE);
+  g_source_set_callback (idle_source, async_alarm_cancel_idle_cb, g_object_ref (self), g_object_unref);
+  g_source_attach (idle_source, main_context);
+  g_source_unref (idle_source);
+
+  g_main_context_unref (main_context);
 }
 
 static void


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