[glib: 1/2] tests: Reduce wakeup interval in gdbus-threading
- From: Sebastian Dröge <sdroege src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/2] tests: Reduce wakeup interval in gdbus-threading
- Date: Fri, 29 Apr 2022 08:05:53 +0000 (UTC)
commit 58f54e8303ea7d55bd3d52742b82e912ade6f616
Author: Philip Withnall <pwithnall endlessos org>
Date: Tue Apr 12 14:39:43 2022 +0100
tests: Reduce wakeup interval in gdbus-threading
When checking that the connection has the expected number of refs, the
test would block on a `GMainContext` iteration for up to 3s before
waking up and failing (if the refcount was still not as expected).
This check was written in the expectation that changing the refcount of
the connection would only happen due to dispatching a source on
`GMainContext` — hence the `GMainContext` would wake up as the refcount
changed.
That’s probably not actually true though. It might be the case that the
connection’s refcount is changed on from the GDBus worker thread, which
would not cause any wakeups on the main thread’s `GMainContext`.
In this case, the `GMainContext` iteration in
`assert_connection_has_one_ref()` would block for the full 3s, and then
wake up and notice the refcount is correct (then the test would
proceed).
That’s fine, apart from the fact that `test_threaded_singleton()` does
this 1000 times. If the slow case is hit on a significant number of
those test runs, the test will take around 3000s to complete, which is
significantly more than meson’s test timeout of 360s. So the test fails
with something like:
```
220/266 glib:gio+slow / gdbus-threading TIMEOUT 360.07 s
--- command ---
G_TEST_SRCDIR='/builds/GNOME/glib/gio/tests' GIO_MODULE_DIR=''
G_TEST_BUILDDIR='/builds/GNOME/glib/_build/gio/tests' /builds/GNOME/glib/_build/gio/tests/gdbus-threading
--- stdout ---
\# random seed: R02S83fe8de22db4d4f376e6d179e2bdd601
1..3
\# Start of gdbus tests
ok 1 /gdbus/delivery-in-thread
ok 2 /gdbus/method-calls-in-thread
\# GLib-GIO-DEBUG: refcount of 0x5602de913660 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
\# GLib-GIO-DEBUG: refcount of 0x5602de913660 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
\# GLib-GIO-DEBUG: refcount of 0x5602de913c60 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
\# GLib-GIO-DEBUG: refcount of 0x5602de913c60 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
\# GLib-GIO-DEBUG: refcount of 0x5602de913260 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
\# GLib-GIO-DEBUG: refcount of 0x5602de913260 is not right (3 rather than 1) in
test_threaded_singleton(), sleeping
```
From this log, it can be seen that the sleep is happening on a different
`GMainContext` every other time, so the test *is* making progress.
Assuming this is a correct diagnosis (it’s a lot of guessing), this
commit tries to fix the test by adding a wakeup timeout to the
`GMainContext` in `assert_connection_has_one_ref()`, which will wake it
up every 50ms to re-check the exit condition.
This polling approach has been taken because it doesn’t seem feasible to
make sure that every `g_object_ref()`/`g_object_unref()` call on a
`GDBusConnection` causes the main context to wake up.
Signed-off-by: Philip Withnall <pwithnall endlessos org>
gio/tests/gdbus-threading.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
---
diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c
index 23dc1fde35..a14a776c5b 100644
--- a/gio/tests/gdbus-threading.c
+++ b/gio/tests/gdbus-threading.c
@@ -44,6 +44,13 @@ timeout_cb (gpointer user_data)
return G_SOURCE_REMOVE;
}
+static gboolean
+wakeup_cb (gpointer user_data)
+{
+ /* nothing to do here */
+ return G_SOURCE_CONTINUE;
+}
+
/* Check that the given @connection has only one ref, waiting to let any pending
* unrefs complete first. This is typically used on the shared connection, to
* ensure it’s in a correct state before beginning the next test. */
@@ -53,15 +60,26 @@ static void
const gchar *calling_function)
{
GSource *timeout_source = NULL;
+ GSource *wakeup_source = NULL;
TimeoutData data = { context, FALSE };
if (g_atomic_int_get (&G_OBJECT (connection)->ref_count) == 1)
return;
+ /* Use two timeout sources: @timeout_source to set a deadline after which the
+ * test will fail if the @connection doesn’t have the right number of refs;
+ * and @wakeup_source to periodically wake the @context up to allow the
+ * termination condition to be checked. This allows the termination condition
+ * to be fulfilled by something which doesn’t wake @context up, such as an
+ * unref happening in the GDBus worker thread. */
timeout_source = g_timeout_source_new_seconds (3);
g_source_set_callback (timeout_source, timeout_cb, &data, NULL);
g_source_attach (timeout_source, context);
+ wakeup_source = g_timeout_source_new (50 /* ms */);
+ g_source_set_callback (wakeup_source, wakeup_cb, NULL, NULL);
+ g_source_attach (wakeup_source, context);
+
while (g_atomic_int_get (&G_OBJECT (connection)->ref_count) != 1 && !data.timed_out)
{
g_debug ("refcount of %p is not right (%u rather than 1) in %s(), sleeping",
@@ -69,6 +87,9 @@ static void
g_main_context_iteration (NULL, TRUE);
}
+ g_source_destroy (wakeup_source);
+ g_source_unref (wakeup_source);
+
g_source_destroy (timeout_source);
g_source_unref (timeout_source);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]