After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 666296 - Race condition in g_thread_xp_get_srwlock
Race condition in g_thread_xp_get_srwlock
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gthread
2.31.x
Other Windows
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2011-12-15 15:55 UTC by rodrigorivascosta
Modified: 2011-12-19 03:21 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
windows XP threads: fix hilariously obvious race (1.48 KB, patch)
2011-12-15 18:29 UTC, Allison Karlitskaya (desrt)
committed Details | Review

Description rodrigorivascosta 2011-12-15 15:55:38 UTC
The testing program glib/mutex.exe fails sometimes with the mingw32 port in Windows XP.

The reason is that in g_thread_xp_get_srwlock() there is a race condition by which two different threads executing it concurrently can create two GThreadSRWLock objects. Then one of them will be thrown into oblivion.

Currently the code is as follows, abbreviated:

static GThreadSRWLock * __stdcall
g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock)
{
  GThreadSRWLock *result;
  result = *lock;
  if (result == NULL)
    {
      EnterCriticalSection (&g_thread_xp_lock);
      result = /* create the GThreadSRWLock */
      *lock = result;
      LeaveCriticalSection (&g_thread_xp_lock);
    }
  return result;
}

If two threads get to EnterCriticalSection() at the same time, one of them will be granted access while the other waits. Then the first one finishes, and the second one... creates other object and overwrites the previous.

My fix would be along the lines of:

static GThreadSRWLock * __stdcall
g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock)
{
  GThreadSRWLock *result;
  result = *lock;
  if (result == NULL)
    {
      EnterCriticalSection (&g_thread_xp_lock);
      /* Double check! */
      result = *lock;
      if (result == NULL)
        {
          result = /* create the GThreadSRWLock */
          *lock = result;
        }
      LeaveCriticalSection (&g_thread_xp_lock);
    }
  return result;
}

I can format a patch if you think it is worth it.
Comment 1 Allison Karlitskaya (desrt) 2011-12-15 18:25:10 UTC
hahah.  This is hilariously bad.  I particularly love the comment I wrote above it to the effect of "this double-checked locking anti-pattern looks bad, but really it's okay".  The logic only applies if you actually remember to do the double-check...
Comment 2 Allison Karlitskaya (desrt) 2011-12-15 18:29:35 UTC
Created attachment 203596 [details] [review]
windows XP threads: fix hilariously obvious race

I tried to do a double-checked lock without the double check.

Rodrigo Rivas Costa caught the problem and suggested the (obviously
correct) fix.
Comment 3 Allison Karlitskaya (desrt) 2011-12-15 18:29:47 UTC
Will this do?
Comment 4 Colin Walters 2011-12-15 18:43:54 UTC
Someone who knows Windows locking will need to double check this patch.
Comment 5 Allison Karlitskaya (desrt) 2011-12-15 19:09:05 UTC
(In reply to comment #4)
> Someone who knows Windows locking will need to double check this patch.

That was dreadful...
Comment 6 Allison Karlitskaya (desrt) 2011-12-16 15:55:20 UTC
Attachment 203596 [details] pushed as 11015f1 - windows XP threads: fix hilariously obvious race