[glib: 10/17] tests: Wait until unwatching the gdbus-testserver name has completed
- From: Sebastian Dröge <sdroege src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 10/17] tests: Wait until unwatching the gdbus-testserver name has completed
- Date: Mon, 24 Feb 2020 10:02:20 +0000 (UTC)
commit af6dbece870a38dcce89ef55922ecfa085925823
Author: Philip Withnall <withnall endlessm com>
Date: Fri Feb 21 12:07:53 2020 +0000
tests: Wait until unwatching the gdbus-testserver name has completed
Previously, the code in `ensure_gdbus_testserver_up()` created a proxy
object and watched its `name-owner` to see when the
`com.example.TestService` name appeared.
This ended up subscribing to three signals (one of them for name
ownership, and two unused for properties of the proxy), and was racy. In
particular, the `name-owner` property could be set before all D-Bus
messages had been processed — it could have been derived from getting
the owner of the name, for example.
This left unprocessed messages hanging around in the `context`, but that
context was never iterated again, which essentially leaked the
references held by those messages. That included a reference to the
`GDBusConnection`.
The first part of the fix is to simplify the code to use
`g_bus_watch_name_on_connection()`, so there’s only one signal
subscription to worry about.
The second part of the fix is to use the `GDestroyNotify` callback for
the watch data to be notified of when all D-Bus traffic has been
processed and the signal unsubscription is complete. At this point, it’s
guaranteed that there are no idle callbacks pending in the
`GMainContext`, since the `GDestroyNotify` callback is the last one
invoked on the `GMainContext`.
Essentially, this commit uses the `GDestroyNotify` callback as a
synchronisation message between the D-Bus worker thread and the thread
calling `ensure_gdbus_testserver_up()`.
Signed-off-by: Philip Withnall <withnall endlessm com>
Fixes: #1515
gio/tests/gdbus-tests.c | 65 +++++++++++++++++++++++++++++++++----------------
1 file changed, 44 insertions(+), 21 deletions(-)
---
diff --git a/gio/tests/gdbus-tests.c b/gio/tests/gdbus-tests.c
index 66f16e02f..bed0d24f7 100644
--- a/gio/tests/gdbus-tests.c
+++ b/gio/tests/gdbus-tests.c
@@ -86,26 +86,52 @@ _give_up (gpointer data)
g_return_val_if_reached (TRUE);
}
+typedef struct
+{
+ GMainContext *context;
+ gboolean name_appeared;
+ gboolean unwatch_complete;
+} WatchData;
+
+static void
+name_appeared_cb (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ WatchData *data = user_data;
+
+ g_assert (name_owner != NULL);
+ data->name_appeared = TRUE;
+ g_main_context_wakeup (data->context);
+}
+
+static void
+watch_free_cb (gpointer user_data)
+{
+ WatchData *data = user_data;
+
+ data->unwatch_complete = TRUE;
+ g_main_context_wakeup (data->context);
+}
+
void
ensure_gdbus_testserver_up (GDBusConnection *connection,
GMainContext *context)
{
- gchar *name_owner;
GSource *timeout_source = NULL;
- GDBusProxy *proxy;
- GError *error = NULL;
+ guint watch_id;
+ WatchData data = { context, FALSE, FALSE };
g_main_context_push_thread_default (context);
- proxy = g_dbus_proxy_new_sync (connection,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL, /* GDBusInterfaceInfo */
- "com.example.TestService", /* name */
- "/com/example/TestObject", /* object path */
- "com.example.Frob", /* interface */
- NULL, /* GCancellable */
- &error);
- g_assert_no_error (error);
+ watch_id = g_bus_watch_name_on_connection (connection,
+ "com.example.TestService",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ name_appeared_cb,
+ NULL,
+ &data,
+ watch_free_cb);
timeout_source = g_timeout_source_new_seconds (60);
g_source_set_callback (timeout_source, _give_up,
@@ -113,20 +139,17 @@ ensure_gdbus_testserver_up (GDBusConnection *connection,
NULL);
g_source_attach (timeout_source, context);
- while (TRUE)
- {
- name_owner = g_dbus_proxy_get_name_owner (proxy);
+ while (!data.name_appeared)
+ g_main_context_iteration (context, TRUE);
- if (name_owner != NULL)
- break;
+ g_bus_unwatch_name (watch_id);
+ watch_id = 0;
- g_main_context_iteration (context, TRUE);
- }
+ while (!data.unwatch_complete)
+ g_main_context_iteration (context, TRUE);
g_source_destroy (timeout_source);
g_source_unref (timeout_source);
- g_free (name_owner);
- g_object_unref (proxy);
g_main_context_pop_thread_default (context);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]