[glib: 1/6] tests: Fix intermittent failure in GCancellableSource test



commit 5b126081576f73159449954f65ab7eeff11145f2
Author: Philip Withnall <withnall endlessm com>
Date:   Wed Jun 17 18:06:20 2020 +0100

    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>

 gio/tests/cancellable.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
---
diff --git a/gio/tests/cancellable.c b/gio/tests/cancellable.c
index e53ae6e7e..8d211857f 100644
--- a/gio/tests/cancellable.c
+++ b/gio/tests/cancellable.c
@@ -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 can’t 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 can’t guarantee to support disposing of a
+       * #GCancellable in a different thread from where it’s created, especially
+       * when signal handlers are connected to it.
+       *
+       * So this is a workaround for a disposal-in-another-thread bug for
+       * #GCancellable, but there’s no hope of debugging and resolving it with
+       * this test setup, and the bug is orthogonal to what’s 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. Can’t 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]