KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

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

Article: Q151869
Product(s): Microsoft C Compiler
Version(s): winnt:4.1
Operating System(s): 
Keyword(s): kbMFC kbThread kbVC410 kbGrpDSMFCATL
Last Modified: 04-AUG-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- The Microsoft Foundation Classes (MFC), used 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 kbVC410 kbGrpDSMFCATL 
Technology        : kbAudDeveloper kbMFC
Version           : winnt:4.1
Issue type        : kbprb

=============================================================================

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.

Copyright Microsoft Corporation 1986-2002.