diff options
author | David Zeuthen <davidz@redhat.com> | 2010-04-27 11:42:44 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-04-27 11:42:44 -0400 |
commit | 8f15ed698bfba4f5c0fa01b4f0020888c57f473e (patch) | |
tree | 492342b2e69e91d851e5da0d19e5bcf771f06c5e | |
parent | d8549b122481ee8f294b7bf3d9589918660d6d71 (diff) |
Add _g_object_wait_for_single_ref() helper
This is needed to ensure that singletons for bus connections gets
cleared properly when the bus goes away. We want this otherwise we
accidentially reuse a closed bus connection.
Apparently this problem never happened for me with D-Bus 1.2.x but it
is pretty evident with D-Bus 1.3.x.
-rw-r--r-- | gdbus/tests/connection.c | 18 | ||||
-rw-r--r-- | gdbus/tests/tests.c | 59 | ||||
-rw-r--r-- | gdbus/tests/tests.h | 25 |
3 files changed, 98 insertions, 4 deletions
diff --git a/gdbus/tests/connection.c b/gdbus/tests/connection.c index f0181d7..5c30959 100644 --- a/gdbus/tests/connection.c +++ b/gdbus/tests/connection.c @@ -100,6 +100,8 @@ test_connection_life_cycle (void) if (!g_dbus_connection_is_closed (c)) _g_assert_signal_received (c, "closed"); g_assert (g_dbus_connection_is_closed (c)); + + _g_object_wait_for_single_ref (c); g_object_unref (c); } @@ -313,6 +315,7 @@ test_connection_send (void) NULL); g_main_loop_run (loop); + _g_object_wait_for_single_ref (c); g_object_unref (c); } @@ -513,14 +516,19 @@ test_connection_signals (void) g_assert_cmpint (count_s2, ==, 2); g_assert_cmpint (count_name_owner_changed, ==, 2); - session_bus_down (); - g_dbus_connection_signal_unsubscribe (c1, s1); g_dbus_connection_signal_unsubscribe (c1, s2); g_dbus_connection_signal_unsubscribe (c1, s3); + + _g_object_wait_for_single_ref (c1); + _g_object_wait_for_single_ref (c2); + _g_object_wait_for_single_ref (c3); + g_object_unref (c1); g_object_unref (c2); g_object_unref (c3); + + session_bus_down (); } /* ---------------------------------------------------------------------------------------------------- */ @@ -560,7 +568,9 @@ test_connection_filter (void) session_bus_up (); - c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + error = NULL; + c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); g_assert (c != NULL); filter_id = g_dbus_connection_add_filter (c, @@ -610,7 +620,7 @@ test_connection_filter (void) g_object_unref (r); g_assert_cmpint (data.num_handled, ==, 3); - + _g_object_wait_for_single_ref (c); g_object_unref (c); g_object_unref (m); diff --git a/gdbus/tests/tests.c b/gdbus/tests/tests.c index 76bc35b..512ffdd 100644 --- a/gdbus/tests/tests.c +++ b/gdbus/tests/tests.c @@ -155,5 +155,64 @@ _g_bus_get_priv (GBusType bus_type, return ret; } +/* ---------------------------------------------------------------------------------------------------- */ + +typedef struct +{ + GMainLoop *loop; + gboolean timed_out; +} WaitSingleRefData; + +static gboolean +on_wait_single_ref_timeout (gpointer user_data) +{ + WaitSingleRefData *data = user_data; + data->timed_out = TRUE; + g_main_loop_quit (data->loop); + return TRUE; +} + +static void +on_wait_for_single_ref_toggled (gpointer user_data, + GObject *object, + gboolean is_last_ref) +{ + WaitSingleRefData *data = user_data; + g_main_loop_quit (data->loop); +} + +gboolean +_g_object_wait_for_single_ref_do (gpointer object) +{ + WaitSingleRefData data; + guint timeout_id; + + data.timed_out = FALSE; + + if (G_OBJECT (object)->ref_count == 1) + goto out; + + data.loop = g_main_loop_new (NULL, FALSE); + timeout_id = g_timeout_add (5 * 1000, + on_wait_single_ref_timeout, + &data); + + g_object_add_toggle_ref (G_OBJECT (object), + on_wait_for_single_ref_toggled, + &data); + g_object_unref (object); + + g_main_loop_run (data.loop); + + g_object_ref (object); + g_object_remove_toggle_ref (object, + on_wait_for_single_ref_toggled, + &data); + + g_source_remove (timeout_id); + g_main_loop_unref (data.loop); + out: + return data.timed_out; +} /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gdbus/tests/tests.h b/gdbus/tests/tests.h index 117570e..366efdc 100644 --- a/gdbus/tests/tests.h +++ b/gdbus/tests/tests.h @@ -116,6 +116,31 @@ GDBusConnection *_g_bus_get_priv (GBusType bus_type, GCancellable *cancellable, GError **error); + +#define _g_object_wait_for_single_ref(object) \ + do \ + { \ + if (!G_IS_OBJECT (object)) \ + { \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, \ + __LINE__, \ + G_STRFUNC, \ + "Not a GObject instance"); \ + } \ + if (_g_object_wait_for_single_ref_do (object)) \ + { \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, \ + __LINE__, \ + G_STRFUNC, \ + "Timed out waiting for single ref"); \ + } \ + } \ + while (FALSE) + +gboolean _g_object_wait_for_single_ref_do (gpointer object); + G_END_DECLS #endif /* __TESTS_H__ */ |