[gnome-online-accounts/gnome-3-10] alarm: Check proper cancellable from timer source ready callback



commit 956fddf222209381ae2419788423344680f37af4
Author: Ray Strode <rstrode redhat com>
Date:   Fri Sep 27 21:02:11 2013 -0400

    alarm: Check proper cancellable from timer source ready callback
    
    on_timer_source_ready is called in two cases:
    
    1) When the timer fires
    2) When the input stream cancellable is cancelled
    
    We attempt to check for this latter case up front at the start of the
    function and react appropriately. We do this by checking if
    self->priv->cancellable is cancelled.
    
    Unforunately, checking self->priv->cancellable isn't always right,
    because self->priv->cancellable isn't always the cancellable associated
    with the input stream.  They can get out of sync, when for instance, the
    alarm expiration time is changed. In this case the old input stream
    cancellable will get cancelled, and self->priv->cancellable will get set
    to the new cancellable.
    
    This commit makes sure the on_timer_source_ready callback always checks
    the cancellable associated with the input stream.  It accomplishes this
    by allocating a GTask and using that as the callback data instead of
    the alarm object directly.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=708975

 src/goaidentity/goaalarm.c |   23 ++++++++++++++++++-----
 1 files changed, 18 insertions(+), 5 deletions(-)
---
diff --git a/src/goaidentity/goaalarm.c b/src/goaidentity/goaalarm.c
index 4b9d086..bcd5d53 100644
--- a/src/goaidentity/goaalarm.c
+++ b/src/goaidentity/goaalarm.c
@@ -359,18 +359,23 @@ out:
 
 #ifdef HAVE_TIMERFD
 static gboolean
-on_timer_source_ready (GObject *stream, GoaAlarm *self)
+on_timer_source_ready (GObject *stream, GTask *task)
 {
   gint64 number_of_fires;
   gssize bytes_read;
   gboolean run_again = FALSE;
   GError *error = NULL;
+  GoaAlarm *self;
+  GCancellable *cancellable;
+
+  self = g_task_get_source_object (task);
+  cancellable = g_task_get_cancellable (task);
 
   g_return_val_if_fail (GOA_IS_ALARM (self), FALSE);
   g_return_val_if_fail (self->priv->type == GOA_ALARM_TYPE_TIMER, FALSE);
 
   g_rec_mutex_lock (&self->priv->lock);
-  if (g_cancellable_is_cancelled (self->priv->cancellable))
+  if (g_cancellable_is_cancelled (cancellable))
     goto out;
 
   bytes_read =
@@ -403,9 +408,14 @@ out:
 }
 
 static void
-clear_timer_source_pointer (GoaAlarm *self)
+clear_timer_source (GTask *task)
 {
+  GoaAlarm *self;
+
+  self = g_task_get_source_object (task);
   self->priv->timer.source = NULL;
+
+  g_object_unref (task);
 }
 #endif
 
@@ -417,6 +427,7 @@ schedule_wakeups_with_timerfd (GoaAlarm *self)
   int fd;
   int result;
   GSource *source;
+  GTask *task;
   static gboolean seen_before = FALSE;
 
   if (!seen_before)
@@ -449,14 +460,16 @@ schedule_wakeups_with_timerfd (GoaAlarm *self)
   self->priv->type = GOA_ALARM_TYPE_TIMER;
   self->priv->timer.stream = g_unix_input_stream_new (fd, TRUE);
 
+  task = g_task_new (self, self->priv->cancellable, NULL, NULL);
+
   source =
     g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM
                                            (self->priv->timer.stream),
                                            self->priv->cancellable);
   self->priv->timer.source = source;
   g_source_set_callback (self->priv->timer.source,
-                         (GSourceFunc) on_timer_source_ready, self,
-                         (GDestroyNotify) clear_timer_source_pointer);
+                         (GSourceFunc) on_timer_source_ready, task,
+                         (GDestroyNotify) clear_timer_source);
   g_source_attach (self->priv->timer.source, self->priv->context);
   g_source_unref (source);
 


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