Solved

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

Posted on 2006-11-20
10
512 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
Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

 

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
 

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

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Building cUrl in Windows v7.43.0 4 32
Move constructor only called if marked noexcept? 6 104
FMX enumerated colours 2 101
No module found pypyodbc, 3 18
When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

803 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