[gnome-online-accounts] alarm: Tag the "cancelled" handler with the correct source and stream



commit f569aabf3c20f51c7b96b7b1692afdcd73916741
Author: Debarshi Ray <debarshir gnome org>
Date:   Mon Nov 11 13:11:28 2013 +0100

    alarm: Tag the "cancelled" handler with the correct source and stream
    
    When a time is set using goa_alarm_set_time, we try to clear the older
    source and stream by cancelling self->priv->cancellable. However,
    before we have had a chance to actually clear them in an idle callback,
    a new source and stream corresponding to the new time is set. This
    causes the older source and stream to be leaked, and instead the newly
    created objects are cleared.
    
    This is wrong. To set things right, we tag the cancelled handler with
    the older source and stream before they are overwritten.
    
    Fixes: https://bugzilla.gnome.org/711696

 src/goaidentity/goaalarm.c |   60 +++++++++++++++++++++++++------------------
 1 files changed, 35 insertions(+), 25 deletions(-)
---
diff --git a/src/goaidentity/goaalarm.c b/src/goaidentity/goaalarm.c
index ec678d7..a79160e 100644
--- a/src/goaidentity/goaalarm.c
+++ b/src/goaidentity/goaalarm.c
@@ -90,16 +90,16 @@ clear_scheduled_immediate_wakeup (GoaAlarm *self)
 }
 
 static void
-clear_scheduled_timer_wakeups (GoaAlarm *self)
+clear_scheduled_timer_wakeups (GoaAlarm *self, GSource *source, GInputStream *stream)
 {
 #ifdef HAVE_TIMERFD
   GError *error;
   gboolean is_closed;
 
-  g_clear_pointer (&self->priv->scheduled_wakeup_source, (GDestroyNotify) g_source_destroy);
+  g_source_destroy (source);
 
   error = NULL;
-  is_closed = g_input_stream_close (self->priv->stream, NULL, &error);
+  is_closed = g_input_stream_close (stream, NULL, &error);
 
   if (!is_closed)
     {
@@ -107,18 +107,18 @@ clear_scheduled_timer_wakeups (GoaAlarm *self)
       g_error_free (error);
     }
 
-  g_clear_object (&self->priv->stream);
+  g_object_unref (stream);
 #endif
 }
 
 static void
-clear_scheduled_timeout_wakeups (GoaAlarm *self)
+clear_scheduled_timeout_wakeups (GoaAlarm *self, GSource *source)
 {
-  g_clear_pointer (&self->priv->scheduled_wakeup_source, (GDestroyNotify) g_source_destroy);
+  g_source_destroy (source);
 }
 
 static void
-clear_scheduled_wakeups (GoaAlarm *self)
+clear_scheduled_wakeups (GoaAlarm *self, GSource *source, GInputStream *stream)
 {
   g_rec_mutex_lock (&self->priv->lock);
   clear_scheduled_immediate_wakeup (self);
@@ -126,11 +126,11 @@ clear_scheduled_wakeups (GoaAlarm *self)
   switch (self->priv->type)
     {
     case GOA_ALARM_TYPE_TIMER:
-      clear_scheduled_timer_wakeups (self);
+      clear_scheduled_timer_wakeups (self, source, stream);
       break;
 
     case GOA_ALARM_TYPE_TIMEOUT:
-      clear_scheduled_timeout_wakeups (self);
+      clear_scheduled_timeout_wakeups (self, source);
       break;
 
     default:
@@ -161,7 +161,7 @@ goa_alarm_finalize (GObject *object)
 {
   GoaAlarm *self = GOA_ALARM (object);
 
-  clear_scheduled_wakeups (self);
+  clear_scheduled_wakeups (self, self->priv->scheduled_wakeup_source, self->priv->stream);
 
   G_OBJECT_CLASS (goa_alarm_parent_class)->finalize (object);
 }
@@ -250,9 +250,18 @@ goa_alarm_init (GoaAlarm *self)
 static gboolean
 async_alarm_cancel_idle_cb (gpointer user_data)
 {
-  GoaAlarm *self = user_data;
+  GoaAlarm *self;
+  GInputStream *stream;
+  GSource *source;
+  GTask *task = G_TASK (user_data);
+  gpointer task_data;
 
-  clear_scheduled_wakeups (self);
+  self = g_task_get_source_object (task);
+  source = (GSource *) g_object_get_data (G_OBJECT (task), "alarm-scheduled-wakeup-source");
+  task_data = g_object_get_data (G_OBJECT (task), "alarm-stream");
+  stream = (task_data == NULL) ? NULL : G_INPUT_STREAM (task_data);
+
+  clear_scheduled_wakeups (self, source, stream);
   return G_SOURCE_REMOVE;
 }
 
@@ -261,13 +270,25 @@ on_cancelled (GCancellable *cancellable, gpointer user_data)
 {
   GoaAlarm *self = GOA_ALARM (user_data);
   GSource *idle_source;
+  GTask *task;
 
+  task = g_task_new (self, NULL, NULL, NULL);
+
+  g_object_set_data_full (G_OBJECT (task),
+                          "alarm-scheduled-wakeup-source",
+                          g_source_ref (self->priv->scheduled_wakeup_source),
+                          (GDestroyNotify) g_source_unref);
+
+  if (self->priv->stream != NULL)
+    g_object_set_data_full (G_OBJECT (task), "alarm-stream", g_object_ref (self->priv->stream), 
g_object_unref);
 
   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_set_callback (idle_source, async_alarm_cancel_idle_cb, g_object_ref (task), g_object_unref);
   g_source_attach (idle_source, self->priv->context);
   g_source_unref (idle_source);
+
+  g_object_unref (task);
 }
 
 static void
@@ -412,17 +433,6 @@ out:
   g_rec_mutex_unlock (&self->priv->lock);
   return run_again;
 }
-
-static void
-clear_timer_source (GTask *task)
-{
-  GoaAlarm *self;
-
-  self = g_task_get_source_object (task);
-  self->priv->scheduled_wakeup_source = NULL;
-
-  g_object_unref (task);
-}
 #endif
 
 static gboolean
@@ -475,7 +485,7 @@ schedule_wakeups_with_timerfd (GoaAlarm *self)
   self->priv->scheduled_wakeup_source = source;
   g_source_set_callback (self->priv->scheduled_wakeup_source,
                          (GSourceFunc) on_timer_source_ready, task,
-                         (GDestroyNotify) clear_timer_source);
+                         (GDestroyNotify) g_object_unref);
   g_source_attach (self->priv->scheduled_wakeup_source, self->priv->context);
   g_source_unref (source);
 


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