deprecated threads: fix race in GStaticRecMutex
authorMark Janossy <janossy.mark@gmail.com>
Fri, 9 Mar 2012 14:54:23 +0000 (09:54 -0500)
committerRyan Lortie <desrt@desrt.ca>
Fri, 9 Mar 2012 14:54:23 +0000 (09:54 -0500)
The very last access to the 'depth' field of GStaticRecMutex in
g_static_rec_mutex_unlock_full() was being performed after dropping the
implementation mutex for the last time.

This allowed the lock to be dropped an additional time if it was
acquired in another thread right at that instant (which is somewhat
likely, since another thread could have just been woken up by the lock
being released).

https://bugzilla.gnome.org/show_bug.cgi?id=670846

glib/deprecated/gthread-deprecated.c

index 13cd1881b411cd86abb44c9a2d41b2187020b9cc..a3cba18e71c6c9210a3412575aab391dd5e7fbb8 100644 (file)
@@ -807,14 +807,17 @@ g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
 {
   GRecMutex *rm;
   gint depth;
+  gint i;
 
   rm = g_static_rec_mutex_get_rec_mutex_impl (mutex);
+
+  /* all access to mutex->depth done while still holding the lock */
   depth = mutex->depth;
-  while (mutex->depth)
-    {
-      mutex->depth--;
-      g_rec_mutex_unlock (rm);
-    }
+  i = mutex->depth;
+  mutex->depth = 0;
+
+  while (i--)
+    g_rec_mutex_unlock (rm);
 
   return depth;
 }