PRB: Incorrect Usage of CSingleLock May Lock Up Mutex Object

Last reviewed: July 31, 1997
Article ID: Q151869
4.10 WINDOWS NT kbprg kbprb

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, 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 reference words: 4.10
KBCategory: kbprg kbprb
KBSubcategory: MfcThreadIss
Keywords : MFCThreadIss kbprb kbprg
Technology : kbMfc
Version : 4.10
Platform : NT WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 31, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.