[glib] gmain: Make GSourceCallback thread-safe



commit d73f8eec4839e35f308d90a321b4bc121f8408e4
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Tue Sep 30 18:53:47 2014 +0100

    gmain: Make GSourceCallback thread-safe
    
    Otherwise there is a race in finalising the GSourceCallback if one
    thread is finishing off a g_main_dispatch() while another thread is
    destroying the GSource which owns the GSourceCallback.
    
    A helgrind log:
    
    ==21707== Possible data race during write of size 4 at 0x54EACB0 by
    thread #12
    ==21707== Locks held: none
    ==21707==    at 0x4ECC174: g_source_callback_unref (gmain.c:1528)
    ==21707==    by 0x4ECD953: g_main_dispatch (gmain.c:3081)
    ==21707==    by 0x4ECE667: g_main_context_dispatch (gmain.c:3673)
    ==21707==    by 0x4ECE859: g_main_context_iterate (gmain.c:3744)
    ==21707==    by 0x4ECEC7F: g_main_loop_run (gmain.c:3938)
    ==21707==    by 0x41C197: some_thread (some-code.c:224)
    ==21707==
    ==21707== This conflicts with a previous write of size 4 by thread #5
    ==21707== Locks held: 1, at address 0x54CF320
    ==21707==    at 0x4ECC174: g_source_callback_unref (gmain.c:1528)
    ==21707==    by 0x4ECB86F: g_source_destroy_internal (gmain.c:1178)
    ==21707==    by 0x4ECB9D4: g_source_destroy (gmain.c:1227)
    ==21707==    by 0x41CF09: some_other_thread (some-other-code.c:410)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=737677

 glib/gmain.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 7e7e44b..2ea6c79 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -300,7 +300,7 @@ struct _GMainContext
 
 struct _GSourceCallback
 {
-  guint ref_count;
+  volatile gint ref_count;
   GSourceFunc func;
   gpointer    data;
   GDestroyNotify notify;
@@ -1551,7 +1551,7 @@ g_source_callback_ref (gpointer cb_data)
 {
   GSourceCallback *callback = cb_data;
 
-  callback->ref_count++;
+  g_atomic_int_inc (&callback->ref_count);
 }
 
 static void
@@ -1559,8 +1559,7 @@ g_source_callback_unref (gpointer cb_data)
 {
   GSourceCallback *callback = cb_data;
 
-  callback->ref_count--;
-  if (callback->ref_count == 0)
+  if (g_atomic_int_dec_and_test (&callback->ref_count))
     {
       if (callback->notify)
         callback->notify (callback->data);


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