Solved

CreateMutex problem...why is it not working correctly?

Posted on 2006-11-20
10
509 Views
Last Modified: 2008-01-09
Here is my function...
My main window is an ATL Dialog window

LONG Test()
      {
      LONG result = 0;
      HANDLE hMutex = ::CreateMutex(NULL, FALSE, _T("MYAPPLICATION_MUTEX"));

      if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0)
            {
            MessageBox(NULL, "WaitForMutex", "", MB_OK);
            ::ReleaseMutex(hMutex);
            }

      ::CloseHandle(hMutex);
      return result;
      }

If I run the app twice, in first app, I click on Test button (which calls Test() function)
The Messagebox "WaitForMutex" shows up (I don't close this messagebox window)

In second instance of app, I do the same, the "WaitForMutex" message box DOES NOT COME UP, the app is waiting (this is of course what I want)
But here's the weird thing... I can go back to original app, and click on the Test button again (which I shouldn't be able to, because MessageBox call is supposed to be a modal call), I get A SECOND "WaitForMutex" messagebox window...(or more if I click on test button more), now even if MessageBox window was modeless, I still SHOULD NOT get more messagebox windows with "WaitForMutex".....Why is this happening???

(Test app does nothing else, I just call Test() function and that's it)
0
Comment
Question by:esgi
  • 5
  • 4
10 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 17985429
To prevent this use first parameter if MessageBox:

MessageBox(hDlg, "WaitForMutex", "", MB_OK);   // hDlg is dialog handle

Or make Test function class member and call this->MessageBox instead of global MessageBox API.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 17985436
Some background: like every modal dialog, MessageBox has its own message loop. This means, dialog message loop continues to run and dialog can handle messages while MessageBox is opened. For example, dialog can repaint itself. However, is dialog is MessageBox parent, it is disabled, and it is impossible to click button again.
0
 

Author Comment

by:esgi
ID: 17985556
MessageBox call is implemented as a member function, which automatically calls function with window handle....

Will explicitly pass parameter...to see if it changes behavior, your second point is valid, but still, why does second MessageBox window show, when I am still waiting on mutex? (mutex is released only when I close MessageBox window), so even based on your second point, since I still have not released mutex yet (confirmed via debugger), why is second MessageBox window popping up? Shouldn't it be waiting like my second app does, till I close MessageBox window and THEN finally release mutex???

0
 

Author Comment

by:esgi
ID: 17985569
The point being...even if I purposely used a modeless window, the second MessageBox popup should not be displayed till I close the first MessageBox window and then release my mutex.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 17985578
If thread owns mutex, any other attempt to get ownership on this mutex from the same thread succeeds immediately. Other threads, from the same or other processes, are waiting, but the same thread always succeeds.

MessageBox(NULL, "WaitForMutex", "", MB_OK);
This is global API - first parameter is NULL, this is window handle. Class function should look like:
MessageBox("WaitForMutex", "", MB_OK);
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:esgi
ID: 17985616
MessageBox(NULL, "WaitForMutex", "", MB_OK);  oops you're right...

If thread owns mutex, any other attempt to get ownership on this mutex from the same thread succeeds immediately. Other threads, from the same or other processes, are waiting, but the same thread always succeeds.

I see.

How do I prevent this? So that everybody waits (including self) until I release mutex?

0
 
LVL 48

Expert Comment

by:AlexFM
ID: 17985644
Please describe what you want to do. To protect code fragment from execution from the same thread you don't need to do anything special - all message handlers are serialized and not executed at the same time.
Situation like yours is possible only when there is additional message loop, but using dialog as MessageBox parent solves this. Is this enough for you?
0
 

Author Comment

by:esgi
ID: 17985671
The MessageBox was just for testing....

Instead of MessageBox, I will have this

....straight C++ code....

Using mutex will force other threads/processes to wait, that call into function of dll (ultimately where this code will reside)

But I also want to prevent myself from calling funtion till I release mutex. How do I do this?

0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 17985717
Usually, there is no need to protect code from execution from the same thread. Such things just don't happen unless you do something special. Accidentally, this happened in your test because of incorrect MessageBox using. I don't think that you need to do something about this.
However, if program really contains code which can call the same function second or more time in the same thread (like your code, or using something like DoEvents), simple boolean flag solves the problem:

BOOL m_bFlag;   // class member

m_bFlag = FALSE;    // initialize in constructor

// critical code section
if ( ! m_bFlag )
{
    m_bFlag = TRUE;
    // ececute code here - including Mutex is necessary
    m_bFlag = FALSE;
}

Notice that code is just skipped without waiting. It is impossible to wait, because this code fragment is executed in the same thread. If you try to wait, program hangs.

Again, I beleive that you don't need this, this is very special situation. Usually code fragments are protected from execution only from different threads.
0
 
LVL 86

Expert Comment

by:jkr
ID: 17987922
If the mutex already exists, 'CreateMutex()' will fail with 'GetLastError()' returning ERROR_ALREADY_EXISTS, the handle will be invalid. That sould be

     HANDLE hMutex = ::CreateMutex(NULL, FALSE, _T("MYAPPLICATION_MUTEX"));

     if (!hMutex) {

         if (ERROR_ALREADY_EXISTS == GetLastError()) {

            hMutex = ::OpenMutex(SYNCHRONIZE,FALSE,_T("MYAPPLICATION_MUTEX"));

         } else {

             // ... other error
         }
     }

This behaviour is well described at http://msdn.microsoft.com/library/en-us/dllproc/base/createmutex.asp ("CreateMutex"):

Return Value

If the function succeeds, the return value is a handle to the newly created mutex object.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object, GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored, and the calling thread is not granted ownership. However, if the caller has limited access rights, the function will fail with ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.

0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now