summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Matos <tiagomatos@gmail.com>2016-01-11 17:04:11 +0100
committerRay Strode <rstrode@redhat.com>2016-01-11 11:23:54 -0500
commit5e57af62866b4d24c68b72b3467797e72de391bd (patch)
tree4422bc266e865675176a24dc8db1ea66d99bb037
parent42b3a34f7b79c3708de9e9e41d567f3c217dd752 (diff)
downloadmutter-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.c68
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);
}