Microsoft KB Archive/151869

= PRB: Incorrect Usage of CSingleLock May Lock Up Mutex Object =

Article ID: 151869

Article Last Modified on 11/21/2006

-

APPLIES TO


 * Microsoft Foundation Class Library 4.2, when used with:
 * Microsoft Visual C++ 4.1 Subscription

-



This article was previously published under Q151869



SYMPTOMS
The CSingleLock class can be used with a CMutex object. An attempt to free the Mutex object by making a call to the documented function CSingleLock::Unlock(LONG, LPLONG) locks up the Mutex. The Mutex is not released even when the CSingleLock object is destroyed.

Instead, the call to CSingleLock::Unlock(void) successfully frees the Mutex.



CAUSE
There is a Boolean variable kept in the class CSingleLock - m_bAcquired. This variable keeps track of the state of the synchronization object. In the case of Mutexes, a value of TRUE (.T.) means that the Mutex object is owned by a thread. The variable is set to FALSE (.F.) when the Mutex is freed.

There are two versions of CSingleLock::Unlock and two versions for CSyncObject::Unlock. One version takes no arguments, while the other one takes two: LONG and LPLONG. CSingleLock::Unlock makes a call to CSyncObject::Unlock only if the m_bAcquired member of CSingleLock is set to TRUE.

Of the two versions of CSingleLock::Unlock, the latter version, with two arguments, should be used only with CSingleLock associated with CSemaphore objects. When used on a CSingleLock object associated with a CMutex, it just returns TRUE. This value is interpreted by CSingleLock::Unlock as though the object got freed and it sets its m_bAcquired member to FALSE. This causes the Mutex to lock up, because any future calls to CSingleLock::Unlock see m_bAcquired to be FALSE and the call to CSyncObject::Unlock is not made. When CSingleLock's destructor gets called, it calls Unlock. However, the same sequence of events prevents the Mutex from being freed.



RESOLUTION
The first version of CSingleLock::Unlock, the one that takes no arguments, should be used. This calls CSyncObject::Unlock(void). This is a virtual function that calls CMutex::Unlock, that, in turn, calls ::ReleaseMutex to free the Mutex object.



STATUS
This behavior is by design.



Sample Code
The following code demonstrates the problem: //.......       CSingleLock* sLock = new CSingleLock (&GlobalMutex); sLock->Lock; //...       sLock->Unlock(1); //...       delete sLock; //.......

This code should be changed to:

//......       CSingleLock* sLock = new CSingleLock (&GlobalMutex); sLock->Lock; //....       sLock->Unlock; //...       delete sLock; //.......

Additional query words: 4.10

Keywords: kbprb kbthread KB151869

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.