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



commit f4c04ad49c29d8f619cb80ef480daa9d4ecdfa38
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 79e2a12..ae749f7 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]