diff options
| author | Chris Coulson <chrisccoulson@googlemail.com> | 2010-02-12 02:47:15 (GMT) |
|---|---|---|
| committer | Richard Hughes <richard@hughsie.com> | 2010-02-12 14:34:08 (GMT) |
| commit | 7380ab4e13db76cb5be2e1bc4a42a810a5261fd4 (patch) | |
| tree | 6ffbb7eb45b0df6d716cccd43aaf8eab8a2fcfb0 | |
| parent | ceca973bcd507ed9fcda69b6a445af756f725198 (diff) | |
| download | gnome-power-manager-7380ab4e13db76cb5be2e1bc4a42a810a5261fd4.zip gnome-power-manager-7380ab4e13db76cb5be2e1bc4a42a810a5261fd4.tar.xz | |
Avoid a race in detecting the idle reset alarm
When the idle timeout alarm fires, a reset alarm is created. If
the IDLETIME counter resets in between the idle timeout alarm being
detected and creating the reset alarm, then the reset alarm will
be missed and we will think that X is idle forever.
This patch creates a reset alarm when creating a EggIdletime
instance, but blocks emitting a "reset" signal from this instance
each time the reset alarm expires, unless the idle timeout alarm
has triggered since the last time the reset alarm expired. This
ensures that we always catch the reset alarm.
| -rw-r--r-- | src/egg-idletime.c | 42 |
1 files changed, 10 insertions, 32 deletions
diff --git a/src/egg-idletime.c b/src/egg-idletime.c index 2145eac..64aa380 100644 --- a/src/egg-idletime.c +++ b/src/egg-idletime.c @@ -146,16 +146,15 @@ egg_idletime_alarm_reset_all (EggIdletime *idletime) g_return_if_fail (EGG_IS_IDLETIME (idletime)); + if (!idletime->priv->reset_set) + return; + /* reset all the alarms (except the reset alarm) to their timeouts */ for (i=1; i<idletime->priv->array->len; i++) { alarm = g_ptr_array_index (idletime->priv->array, i); egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE); } - /* set the reset alarm to be disabled */ - alarm = g_ptr_array_index (idletime->priv->array, 0); - egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_DISABLED); - /* emit signal so say we've reset all timers */ g_signal_emit (idletime, signals [SIGNAL_RESET], 0); @@ -180,33 +179,6 @@ egg_idletime_alarm_find_id (EggIdletime *idletime, guint id) } /** - * egg_idletime_set_reset_alarm: - */ -static void -egg_idletime_set_reset_alarm (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event) -{ - EggIdletimeAlarm *alarm; - int overflow; - XSyncValue add; - - alarm = egg_idletime_alarm_find_id (idletime, 0); - - if (!idletime->priv->reset_set) { - /* don't match on the current value because - * XSyncNegativeComparison means less or equal. */ - XSyncIntToValue (&add, -1); - XSyncValueAdd (&alarm->timeout, alarm_event->counter_value, add, &overflow); - - /* set the reset alarm to fire the next time - * idletime->priv->idle_counter < the current counter value */ - egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_NEGATIVE); - - /* don't try to set this again if multiple timers are going off in sequence */ - idletime->priv->reset_set = TRUE; - } -} - -/** * egg_idletime_alarm_find_event: */ static EggIdletimeAlarm * @@ -254,7 +226,7 @@ egg_idletime_event_filter_cb (GdkXEvent *gdkxevent, GdkEvent *event, gpointer da g_signal_emit (alarm->idletime, signals [SIGNAL_ALARM_EXPIRED], 0, alarm->id); /* we need the first alarm to go off to set the reset alarm */ - egg_idletime_set_reset_alarm (idletime, alarm_event); + idletime->priv->reset_set = TRUE; out: /* don't propagate */ return GDK_FILTER_REMOVE; @@ -416,6 +388,12 @@ egg_idletime_init (EggIdletime *idletime) /* create a reset alarm */ alarm = egg_idletime_alarm_new (idletime, 0); g_ptr_array_add (idletime->priv->array, alarm); + + XSyncIntToValue (&alarm->timeout, 0); + + /* set the reset alarm to fire when the + * idle_counter == 0 */ + egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_NEGATIVE); } /** |