[gnome-desktop] IdleMonitor: protect watches from being freed while in flight
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] IdleMonitor: protect watches from being freed while in flight
- Date: Wed, 4 Sep 2013 21:57:45 +0000 (UTC)
commit 91727625fc92c5f44208c3d540ca6e12157a68d6
Author: Giovanni Campagna <gcampagn redhat com>
Date: Tue Sep 3 18:39:04 2013 +0200
IdleMonitor: protect watches from being freed while in flight
If you added an idle watch and then immediately removed it, it
was possible that the watch was freed before the dbus call was
handled by mutter, thus causing a crash later one.
Prevent that by reference counting the watch structures.
https://bugzilla.gnome.org/show_bug.cgi?id=707396
libgnome-desktop/gnome-idle-monitor.c | 39 +++++++++++++++++++++++++++++---
1 files changed, 35 insertions(+), 4 deletions(-)
---
diff --git a/libgnome-desktop/gnome-idle-monitor.c b/libgnome-desktop/gnome-idle-monitor.c
index 721bba1..6af1343 100644
--- a/libgnome-desktop/gnome-idle-monitor.c
+++ b/libgnome-desktop/gnome-idle-monitor.c
@@ -48,6 +48,8 @@ struct _GnomeIdleMonitorPrivate
typedef struct
{
+ int ref_count;
+ gboolean dead;
GnomeIdleMonitor *monitor;
guint id;
guint upstream_id;
@@ -111,8 +113,12 @@ get_next_watch_serial (void)
}
static void
-idle_monitor_watch_free (GnomeIdleMonitorWatch *watch)
+idle_monitor_watch_unref (GnomeIdleMonitorWatch *watch)
{
+ watch->ref_count--;
+ if (watch->ref_count)
+ return;
+
if (watch->notify != NULL)
watch->notify (watch->user_data);
@@ -124,6 +130,22 @@ idle_monitor_watch_free (GnomeIdleMonitorWatch *watch)
g_slice_free (GnomeIdleMonitorWatch, watch);
}
+static GnomeIdleMonitorWatch *
+idle_monitor_watch_ref (GnomeIdleMonitorWatch *watch)
+{
+ g_assert (watch->ref_count > 0);
+
+ watch->ref_count++;
+ return watch;
+}
+
+static void
+idle_monitor_watch_destroy (GnomeIdleMonitorWatch *watch)
+{
+ watch->dead = TRUE;
+ idle_monitor_watch_unref (watch);
+}
+
static void
gnome_idle_monitor_dispose (GObject *object)
{
@@ -343,7 +365,7 @@ gnome_idle_monitor_init (GnomeIdleMonitor *monitor)
monitor->priv->watches = g_hash_table_new_full (NULL,
NULL,
NULL,
- (GDestroyNotify)idle_monitor_watch_free);
+ (GDestroyNotify)idle_monitor_watch_destroy);
monitor->priv->watches_by_upstream_id = g_hash_table_new (NULL, NULL);
monitor->priv->cancellable = g_cancellable_new ();
@@ -390,6 +412,7 @@ make_watch (GnomeIdleMonitor *monitor,
GnomeIdleMonitorWatch *watch;
watch = g_slice_new0 (GnomeIdleMonitorWatch);
+ watch->ref_count = 1;
watch->id = get_next_watch_serial ();
watch->monitor = monitor;
watch->callback = callback;
@@ -415,11 +438,18 @@ on_watch_added (GObject *object,
if (!res) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error_free (error);
+ idle_monitor_watch_unref (watch);
return;
}
g_warning ("Failed to acquire idle monitor proxy: %s", error->message);
g_error_free (error);
+ idle_monitor_watch_unref (watch);
+ return;
+ }
+
+ if (watch->dead) {
+ idle_monitor_watch_unref (watch);
return;
}
@@ -429,6 +459,7 @@ on_watch_added (GObject *object,
g_hash_table_insert (monitor->priv->watches_by_upstream_id,
GINT_TO_POINTER (watch->upstream_id), watch);
+ idle_monitor_watch_unref (watch);
}
static void
@@ -438,7 +469,7 @@ add_idle_watch (GnomeIdleMonitor *monitor,
meta_dbus_idle_monitor_call_add_idle_watch (monitor->priv->proxy,
watch->timeout_msec,
monitor->priv->cancellable,
- on_watch_added, watch);
+ on_watch_added, idle_monitor_watch_ref (watch));
}
static void
@@ -447,7 +478,7 @@ add_active_watch (GnomeIdleMonitor *monitor,
{
meta_dbus_idle_monitor_call_add_user_active_watch (monitor->priv->proxy,
monitor->priv->cancellable,
- on_watch_added, watch);
+ on_watch_added, idle_monitor_watch_ref (watch));
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]