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



commit f3052079ab680dfe0008d3b21f3b83f100e5445e
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 05160af..afcb9d6 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]