Davide
Davide

Reputation: 53

C++ - Cannot See Created Mutex Using WinObj

I am using this really simple code to try to create a mutex

int main(){
    
    HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
    if(!hMutex){
        
        wchar_t buff[1000];

        _snwprintf(buff, sizeof(buff), L"Failed to create mutex (Error: %d)", ::GetLastError());   
         
        ::MessageBox(nullptr, buff, L"Single Instance", MB_OK);


        return 0x1;
    } else {
        ::MessageBox(nullptr, L"Mutex Created", L"Single Instance", MB_OK);
    }
    
    return 0x0;
}

And I get the message "Mutex Created" like if it is correctly created, but when I try to search it using the tool WinObj of SysInternals I can't find it.

Also if I restart the program many times while another instance is running I always get the message "Mutex Created" and never an error because the mutex already exists.

I'm trying it on a Windows 7 VM.

What I'm doing wrong?

Ah I'm compiling on Linux using:

i686-w64-mingw32-g++ -static-libgcc -static-libstdc++ Mutex.cpp

Thank you!

Upvotes: 2

Views: 494

Answers (1)

wohlstad
wohlstad

Reputation: 28074

In order to use a Windows mutex (whether a named one like yours or an unnamed one), you need to use the following Win APIs:

  1. CreateMutex - to obtain a handle to the mutex Windows kernel object. In case of a named mutex (like yours) multiple processes should succeed to get this handle. The first one will cause the OS to create a new named mutex, and the others will get a handle referring to that same mutex.
    In case the function succeeds and you get a valid handle to the named mutex, you can determine whether the mutex already existed (i.e. that another process already created the mutex) by checking if GetLastError returns ERROR_ALREADY_EXISTS.
  2. WaitForSingleObject - to lock the mutex for exclusive access. This function is actually not specific to mutex and is used for many kernel objects. See the link above for more info about Windows kernel objects.
  3. ReleaseMutex - to unlock the mutex.
  4. CloseHandle - to release the acquired mutex handle (as usual with Windows handles). The OS will automatically close the handle when the process exists, but it is good practice to do it explicitly.

A complete example:

#include <Windows.h>
#include <iostream>

int main()
{
    // Create the mutex handle:
    HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
    if (!hMutex)
    {
        std::cout << "Failed to create mutex handle." << std::endl;
        // Handle error: ...
        return 1;
    }
    bool bAlreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS);
    std::cout << "Succeeded to create mutex handle. Already existed: " << (bAlreadyExisted ? "YES" : "NO") << std::endl;

    // Lock the mutex:
    std::cout << "Atempting to lock ..." << std::endl;
    DWORD dwRes = ::WaitForSingleObject(hMutex, INFINITE);
    if (dwRes != WAIT_OBJECT_0)
    {
        std::cout << "Failed to lock the mutex" << std::endl;
        // Handle error: ...
        return 1;
    }
    std::cout << "Locked." << std::endl;

    // Do something that required the lock: ...
    std::cout << "Press ENTER to unlock." << std::endl;
    std::getchar();

    // Unlock the mutex:
    if (!::ReleaseMutex(hMutex))
    {
        std::cout << "Failed to unlock the mutex" << std::endl;
        // Handle error: ...
        return 1;
    }
    std::cout << "Unlocked." << std::endl;

    // Free the handle:
    if (!CloseHandle(hMutex))
    {
        std::cout << "Failed to close the mutex handle" << std::endl;
        // Handle error: ...
        return 1;
    }

    return 0;
}

Error handling:
As you can see in the documentation links above, when CreateMutex,ReleaseMutex and CloseHandle fail, you should call GetLastError to get more info about the error. WaitForSingleObject will return a specific return value upon error (see the documentation link above). This should be done as a part of the // Handle error: ... sections.

Note:
Using a named mutex for IPC (interprocess communication) might be the only good use case for native Windows mutexes.
For a regular unnamed mutex it's better to use one of the available standard library types of mutexes: std::mutex,std::recursive_mutex,std::recursive_timed_mutex (the last 2 support repeated lock by a thread, similarly to Windows mutex).

Upvotes: 3

Related Questions