I am using this really simple code to try to create a mutex
int main(){
HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
if(!hMutex){
char buff[1000];
snprintf(buff, sizeof(buff), "Failed to create mutex (Error: %d)", ::GetLastError());
std::string s(buff);
std::wstring stemp = std::wstring(s.begin(), s.end());
LPCWSTR sw = stemp.c_str();
::MessageBox(nullptr, sw, 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!
CodePudding user response:
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:
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.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.ReleaseMutex
- to unlock the mutex.
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;
}
std::cout << "Succeeded to create mutex handle." << 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;
return 0;
}
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 std::mutex
.