[Development] QBasicMutex::lockInternal() race condition?

Olivier Goffart olivier at woboq.com
Thu Sep 20 17:38:40 CEST 2012


On Thursday 20 September 2012 15:30:32 Tony Van Eerd wrote:
> I've been looking at the implementation of QMutex (et al), via woboq, ie
> http://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.cpp.html.  (nice
> work on the code viewer, by the way!)

Thanks :-)

> 
> I'm wondering if there isn't a subtle race condition in lockInternal() at
> line 358:
> 
> 358                 if (!d->ref())
> 359                     continue; //that QMutexData was already released
> 
> In the case where you pick up the d_ptr that was allocated by another thread
> - how do you know that d is still valid?
> 
> IIUC, d comes from the freelist, so it is probably never actually an invalid
> pointer, but how do you know that:
> 
> 1 this mutex was locked by another thread
> 2 this mutex  was unlocked by that (or yet another) thread
> 3 the d_ptr was released
> 4 the released pointer was recycled into another mutex via the freelist
> 5 then line 358 runs.
> 
> ie d->ref() passes, but 'd' is for the wrong mutex?

We check for that case shortly after:

361	  if (d != d_ptr.loadAcquire()) {
362	     //Either the mutex is already unlocked, or relocked with another mutex
363	     d->deref();
364	     continue;
365	  }

If we referenced the wrong mutex, we will unreference it and continue.


I have a change to document more the internal, but it is not merged yet.
https://codereview.qt-project.org/33739


-- 
Olivier

Woboq - Qt services and support - http://woboq.com



More information about the Development mailing list