[gnome-online-accounts/f19] Another attempt at fixing the busy loop on kinit
Ray Strode
rstrode at fedoraproject.org
Sat Sep 28 01:20:47 UTC 2013
commit f6479258696c1093d702f229d575741d3580fb6a
Author: Ray Strode <rstrode at redhat.com>
Date: Fri Sep 27 21:20:21 2013 -0400
Another attempt at fixing the busy loop on kinit
Resolves: #1005619
fix-kinit-cpu-loop.patch | 320 ++++++++++++++++++++++++++++++++++++++++++++
gnome-online-accounts.spec | 6 +-
2 files changed, 325 insertions(+), 1 deletions(-)
---
diff --git a/fix-kinit-cpu-loop.patch b/fix-kinit-cpu-loop.patch
index 8cb722b..0eaae38 100644
--- a/fix-kinit-cpu-loop.patch
+++ b/fix-kinit-cpu-loop.patch
@@ -93,3 +93,323 @@ index ae749f7..e9b904b 100644
--
1.8.3.1
+From 02729d9902daba9645eaf654e163e85ae5148407 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode at redhat.com>
+Date: Fri, 27 Sep 2013 20:39:47 -0400
+Subject: [PATCH 1/2] goaidentity: print warning if timerfd I/O fails
+
+Reading from a timerfd shouldn't fail, but if it
+does we should print what's going on.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=708975
+---
+ src/goaidentity/goaalarm.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/src/goaidentity/goaalarm.c b/src/goaidentity/goaalarm.c
+index e9b904b..4b9d086 100644
+--- a/src/goaidentity/goaalarm.c
++++ b/src/goaidentity/goaalarm.c
+@@ -337,72 +337,81 @@ fire_or_rearm_alarm (GoaAlarm *self)
+ else if (time_until_fire > 0 && previous_time_until_fire <= 0)
+ {
+ rearm_alarm (self);
+ }
+ }
+ }
+
+ static gboolean
+ on_immediate_wakeup_source_ready (GoaAlarm *self)
+ {
+ g_return_val_if_fail (self->priv->type != GOA_ALARM_TYPE_UNSCHEDULED, FALSE);
+
+ g_rec_mutex_lock (&self->priv->lock);
+ if (g_cancellable_is_cancelled (self->priv->cancellable))
+ goto out;
+
+ fire_or_rearm_alarm (self);
+
+ out:
+ g_rec_mutex_unlock (&self->priv->lock);
+ return FALSE;
+ }
+
+ #ifdef HAVE_TIMERFD
+ static gboolean
+ on_timer_source_ready (GObject *stream, GoaAlarm *self)
+ {
+ gint64 number_of_fires;
+ gssize bytes_read;
+ gboolean run_again = FALSE;
++ GError *error = NULL;
+
+ 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))
+ goto out;
+
+ bytes_read =
+ g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
+ &number_of_fires, sizeof (gint64),
+- NULL, NULL);
++ NULL, &error);
++
++ if (bytes_read < 0)
++ {
++ goa_warning ("GoaAlarm: failed to read from timer fd: %s\n",
++ error->message);
++ g_error_free (error);
++ goto out;
++ }
+
+ if (bytes_read == sizeof (gint64))
+ {
+ if (number_of_fires < 0 || number_of_fires > 1)
+ {
+ goa_warning ("GoaAlarm: expected timerfd to report firing once,"
+ "but it reported firing %ld times\n", (long) number_of_fires);
+ }
+ }
+
+ fire_or_rearm_alarm (self);
+ run_again = TRUE;
+ out:
+ g_rec_mutex_unlock (&self->priv->lock);
+ return run_again;
+ }
+
+ static void
+ clear_timer_source_pointer (GoaAlarm *self)
+ {
+ self->priv->timer.source = NULL;
+ }
+ #endif
+
+ static gboolean
+ schedule_wakeups_with_timerfd (GoaAlarm *self)
+ {
+ #ifdef HAVE_TIMERFD
+ struct itimerspec timer_spec;
+ int fd;
+--
+1.8.3.1
+
+
+From d8d87593bcfa1127c29fa6643600a20e986ec5ea Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode at redhat.com>
+Date: Fri, 27 Sep 2013 21:02:11 -0400
+Subject: [PATCH 2/2] identity: 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 file 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
+@@ -332,158 +332,171 @@ fire_or_rearm_alarm (GoaAlarm *self)
+ /* If, according to the time, we're before when we should fire,
+ * and we previously fired the alarm, then we've jumped back in
+ * time and need to rearm the alarm.
+ */
+ }
+ else if (time_until_fire > 0 && previous_time_until_fire <= 0)
+ {
+ rearm_alarm (self);
+ }
+ }
+ }
+
+ static gboolean
+ on_immediate_wakeup_source_ready (GoaAlarm *self)
+ {
+ g_return_val_if_fail (self->priv->type != GOA_ALARM_TYPE_UNSCHEDULED, FALSE);
+
+ g_rec_mutex_lock (&self->priv->lock);
+ if (g_cancellable_is_cancelled (self->priv->cancellable))
+ goto out;
+
+ fire_or_rearm_alarm (self);
+
+ out:
+ g_rec_mutex_unlock (&self->priv->lock);
+ return FALSE;
+ }
+
+ #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 =
+ g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
+ &number_of_fires, sizeof (gint64),
+ NULL, &error);
+
+ if (bytes_read < 0)
+ {
+ goa_warning ("GoaAlarm: failed to read from timer fd: %s\n",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (bytes_read == sizeof (gint64))
+ {
+ if (number_of_fires < 0 || number_of_fires > 1)
+ {
+ goa_warning ("GoaAlarm: expected timerfd to report firing once,"
+ "but it reported firing %ld times\n", (long) number_of_fires);
+ }
+ }
+
+ fire_or_rearm_alarm (self);
+ run_again = TRUE;
+ out:
+ g_rec_mutex_unlock (&self->priv->lock);
+ return run_again;
+ }
+
+ 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
+
+ static gboolean
+ schedule_wakeups_with_timerfd (GoaAlarm *self)
+ {
+ #ifdef HAVE_TIMERFD
+ struct itimerspec timer_spec;
+ int fd;
+ int result;
+ GSource *source;
++ GTask *task;
+ static gboolean seen_before = FALSE;
+
+ if (!seen_before)
+ {
+ goa_debug ("GoaAlarm: trying to use kernel timer");
+ seen_before = TRUE;
+ }
+
+ fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK);
+
+ if (fd < 0)
+ {
+ goa_debug ("GoaAlarm: could not create timer fd: %m");
+ return FALSE;
+ }
+
+ memset (&timer_spec, 0, sizeof (timer_spec));
+ timer_spec.it_value.tv_sec = g_date_time_to_unix (self->priv->time) + 1;
+
+ result = timerfd_settime (fd,
+ TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
+ &timer_spec, NULL);
+
+ if (result < 0)
+ {
+ goa_debug ("GoaAlarm: could not set timer: %m");
+ return FALSE;
+ }
+
+ 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);
+
+ return TRUE;
+
+ #endif /*HAVE_TIMERFD */
+
+ return FALSE;
+ }
+
+ static gboolean
+ on_timeout_source_ready (GoaAlarm *self)
+ {
+ g_return_val_if_fail (GOA_IS_ALARM (self), FALSE);
+
+ g_rec_mutex_lock (&self->priv->lock);
+
+ if (g_cancellable_is_cancelled (self->priv->cancellable) ||
+ self->priv->type == GOA_ALARM_TYPE_UNSCHEDULED)
+ goto out;
+
+ fire_or_rearm_alarm (self);
+
+ if (g_cancellable_is_cancelled (self->priv->cancellable))
+ goto out;
+
+ schedule_wakeups_with_timeout_source (self);
+
+ out:
+ g_rec_mutex_unlock (&self->priv->lock);
+--
+1.8.3.1
+
diff --git a/gnome-online-accounts.spec b/gnome-online-accounts.spec
index 29b75f0..a617ace 100644
--- a/gnome-online-accounts.spec
+++ b/gnome-online-accounts.spec
@@ -1,6 +1,6 @@
Name: gnome-online-accounts
Version: 3.8.3
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: Provide online accounts information
Group: System Environment/Libraries
@@ -102,6 +102,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_libdir}/goa-1.0/include
%changelog
+* Fri Sep 27 2013 Ray Strode <rstrode at redhat.com> 3.8.3-3
+- Another attempt at fixing the busy loop on kinit
+ Resolves: #1005619
+
* Fri Sep 27 2013 Ray Strode <rstrode at redhat.com> 3.8.3-2
- Fix busy loop on kinit
Resolves: #1005619
More information about the scm-commits
mailing list