diff options
author | Rui Matos <tiagomatos@gmail.com> | 2016-01-11 17:04:11 +0100 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2016-01-11 11:23:54 -0500 |
commit | 5e57af62866b4d24c68b72b3467797e72de391bd (patch) | |
tree | 4422bc266e865675176a24dc8db1ea66d99bb037 | |
parent | 42b3a34f7b79c3708de9e9e41d567f3c217dd752 (diff) | |
download | mutter-5e57af62866b4d24c68b72b3467797e72de391bd.tar.gz |
idle-monitor-native: Don't leak user active watches
This fixes an issue analogous to bug 760330 for the X11 backend,
except on this backend we wouldn't crash accessing free'd memory.
Instead we're leaking watches since we steal them from the hash table
which means that when they're removed in
_meta_idle_monitor_watch_fire() they're no longer there and thus
they're never free'd.
https://bugzilla.gnome.org/show_bug.cgi?id=760476
-rw-r--r-- | src/backends/native/meta-idle-monitor-native.c | 68 |
1 files changed, 24 insertions, 44 deletions
diff --git a/src/backends/native/meta-idle-monitor-native.c b/src/backends/native/meta-idle-monitor-native.c index 13d8d516f..da1ad06d1 100644 --- a/src/backends/native/meta-idle-monitor-native.c +++ b/src/backends/native/meta-idle-monitor-native.c @@ -164,56 +164,36 @@ meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native) monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); } -typedef struct { - MetaIdleMonitorNative *monitor_native; - GList *fired_watches; -} CheckNativeClosure; - -static gboolean -check_native_watch (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaIdleMonitorWatchNative *watch_native = value; - MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native; - CheckNativeClosure *closure = user_data; - gboolean steal; - - if (watch->timeout_msec == 0) - { - closure->fired_watches = g_list_prepend (closure->fired_watches, watch); - steal = TRUE; - } - else - { - g_source_set_ready_time (watch_native->timeout_source, - closure->monitor_native->last_event_time + - watch->timeout_msec * 1000); - steal = FALSE; - } - - return steal; -} - -static void -fire_native_watch (gpointer watch, - gpointer data) -{ - _meta_idle_monitor_watch_fire (watch); -} - void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor) { MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor); - CheckNativeClosure closure; + GList *node, *watch_ids; monitor_native->last_event_time = g_get_monotonic_time (); - closure.monitor_native = monitor_native; - closure.fired_watches = NULL; - g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure); + watch_ids = g_hash_table_get_keys (monitor->watches); + + for (node = watch_ids; node != NULL; node = node->next) + { + guint watch_id = GPOINTER_TO_UINT (node->data); + MetaIdleMonitorWatchNative *watch; + + watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id)); + if (!watch) + continue; + + if (watch->base.timeout_msec == 0) + { + _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); + } + else + { + g_source_set_ready_time (watch->timeout_source, + monitor_native->last_event_time + + watch->base.timeout_msec * 1000); + } + } - g_list_foreach (closure.fired_watches, fire_native_watch, NULL); - g_list_free (closure.fired_watches); + g_list_free (watch_ids); } |