PRB: Incorrect Usage of CSingleLock May Lock Up Mutex Object
ID: Q151869
|
The information in this article applies to:
-
The Microsoft Foundation Classes (MFC), included with:
-
Microsoft Visual C++, 32-bit Editions, version 4.1
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.
MORE INFORMATION
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 : kbMFC kbThread kbVC
Version : 4.10
Platform : NT WINDOWS
Issue type :