tests: Fix intermittent failure in GCancellableSource test

It seems that allowing the GCancellable to be finalised in either the
main thread or the worker thread sometimes leads to crashes when running
on CI.

I cannot reproduce these crashes locally, and various analyses with
memcheck, drd and helgrind have failed to give any clues.

Fix this for this particular test case by deferring destruction of the
`GCancellable` instances until after the worker thread has joined.
That’s OK because this test is specifically checking a race between
`g_cancellable_cancel()` and disposal of a `GCancellableSource`.

The underlying bug remains unfixed, though, and I can only hope that we
eventually find a reliable way of reproducing it so it can be analysed
and fixed.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
Philip Withnall 2020-06-17 18:06:20 +01:00
parent b79635b391
commit 5b12608157

View File

@ -270,6 +270,7 @@ test_cancellable_source_threaded_dispose (void)
ThreadedDisposeData data;
GThread *thread = NULL;
guint i;
GPtrArray *cancellables_pending_unref = g_ptr_array_new_with_free_func (g_object_unref);
g_test_summary ("Test a thread race between disposing of a GCancellableSource "
"(in one thread) and cancelling the GCancellable it refers "
@ -309,7 +310,18 @@ test_cancellable_source_threaded_dispose (void)
/* Race with disposal of the cancellable source. */
g_cancellable_cancel (cancellable);
g_object_unref (cancellable);
/* This thread cant drop its reference to the #GCancellable here, as it
* might not be the final reference (depending on how the race is
* resolved: #GCancellableSource holds a strong ref on the #GCancellable),
* and at this point we cant guarantee to support disposing of a
* #GCancellable in a different thread from where its created, especially
* when signal handlers are connected to it.
*
* So this is a workaround for a disposal-in-another-thread bug for
* #GCancellable, but theres no hope of debugging and resolving it with
* this test setup, and the bug is orthogonal to whats being tested here
* (a race between #GCancellable and #GCancellableSource). */
g_ptr_array_add (cancellables_pending_unref, g_steal_pointer (&cancellable));
}
/* Indicate that the test has finished. Cant use %NULL as #GAsyncQueue
@ -322,6 +334,8 @@ test_cancellable_source_threaded_dispose (void)
g_async_queue_unref (data.cancellable_source_queue);
g_mutex_clear (&data.mutex);
g_cond_clear (&data.cond);
g_ptr_array_unref (cancellables_pending_unref);
}
int