[telepathy-gabble/master] gabble_idle_add_weak(): don't remove the weak reference twice
Dafydd Harries
dafydd.harries at collabora.co.uk
Fri Aug 14 05:34:24 PDT 2009
Also, add a test.
---
src/util.c | 16 +++++++--
tests/Makefile.am | 1 +
tests/test-gabble-idle-weak.c | 77 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 3 deletions(-)
create mode 100644 tests/test-gabble-idle-weak.c
diff --git a/src/util.c b/src/util.c
index c3d5b3d..78122dc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1030,8 +1030,6 @@ idle_removed (gpointer data)
{
WeakIdleCtx *ctx = (WeakIdleCtx *) data;
- g_object_weak_unref (
- ctx->object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id));
g_slice_free (WeakIdleCtx, ctx);
}
@@ -1039,8 +1037,20 @@ static gboolean
idle_callback (gpointer data)
{
WeakIdleCtx *ctx = (WeakIdleCtx *) data;
+ gboolean ret;
- return ctx->function ((gpointer) ctx->object);
+ if (ctx->function ((gpointer) ctx->object))
+ {
+ return TRUE;
+ }
+ else
+ {
+ g_object_weak_unref (
+ ctx->object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id));
+ return FALSE;
+ }
+
+ return ret;
}
/* Like g_idle_add(), but cancel the callback if the provided object is
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 356b472..6e58fea 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -7,6 +7,7 @@ noinst_PROGRAMS = \
test-base64 \
test-caps-hash \
test-dtube-unique-names \
+ test-gabble-idle-weak \
test-handles \
test-jid-decode \
test-parse-message \
diff --git a/tests/test-gabble-idle-weak.c b/tests/test-gabble-idle-weak.c
new file mode 100644
index 0000000..3342227
--- /dev/null
+++ b/tests/test-gabble-idle-weak.c
@@ -0,0 +1,77 @@
+
+#include <glib.h>
+
+#include "src/util.h"
+
+static gboolean idle_quit_called = FALSE;
+static GMainLoop *loop = NULL;
+static GObject *object;
+
+static gboolean
+idle_quit (gpointer data)
+{
+ /* This callback should be called exactly once per test. */
+ g_assert (idle_quit_called == FALSE);
+ idle_quit_called = TRUE;
+ g_assert (data == object);
+ g_main_loop_quit (loop);
+ return FALSE;
+}
+
+/* Test 1: Source removed before object finalised. */
+static void
+test_1 (void)
+{
+ idle_quit_called = FALSE;
+ object = g_object_new (G_TYPE_OBJECT, NULL);
+ g_object_set_data (object, "foo", GUINT_TO_POINTER (42));
+ loop = g_main_loop_new (NULL, FALSE);
+
+ gabble_idle_add_weak (idle_quit, object);
+ g_main_loop_run (loop);
+
+ g_object_unref (object);
+ g_main_loop_unref (loop);
+
+ g_assert (idle_quit_called == TRUE);
+}
+
+static gboolean
+idle_unref (gpointer data)
+{
+ g_object_unref (G_OBJECT (data));
+ return FALSE;
+}
+
+/* Test 2: Object finalised before source removed. */
+static void
+test_2 (void)
+{
+ idle_quit_called = FALSE;
+ object = g_object_new (G_TYPE_OBJECT, NULL);
+ g_object_set_data (object, "foo", GUINT_TO_POINTER (42));
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_idle_add (idle_unref, object);
+ /* This idle quit shouldn't be called because the previous idle will unref
+ * the object and trigger the weak notify.
+ */
+ gabble_idle_add_weak (idle_quit, object);
+ /* This one will be called, however. */
+ g_idle_add (idle_quit, object);
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+
+ g_assert (idle_quit_called == TRUE);
+}
+
+int
+main (void)
+{
+ g_type_init ();
+ test_1();
+ test_2();
+ return 0;
+}
+
--
1.5.6.5
More information about the telepathy-commits
mailing list