Hello, I have to processes in memory. The first one starts and creates a mutex. Then the second does a loop every 15 seconds trying to create the same mutex or else it does not start its main functions, so only one of the processes can be running at once. The problem is that when i exit the first process, the second process still thinks the mutex still exists. So basically, when I close an app the improper way, the mutex is not destroyed.
You should be using a wait function (http://msdn2.microsoft.com/en-us/library/ms687069.aspx) to suspend the operations of the second application. The mutex will be signaled when the first application releases ownership (after claling ReleaseMutex or terminating).
Ehtyar.
that's not what i want to do. When the app crashes, i want the mutex to be destroyed with it, which is not what is currently happening.
Round-about solution: create a third, supervisory thread, which monitors the other threads and terminates duplicates of process A or B?
Well, Windows does take care of this problem quite effectively. You can use OpenMutex to obtain a handle, if the return value from GetLastError is WAIT_ABANDONED then the owner process has terminated without releasing the mutex and you can take it from there, if the error is ERROR_FILE_NOT_FOUND then the mutex does not exist. Once the new process has received a WAIT_ABANDONED error it assumes ownership of the mutex and can destroy it if needed. At least that's how I understand it, can't say I have had the problem though.
hmm donkey that sounds like a good idea but it still doesn't work for some reason. OpenMutex just returns a random hex value that increases each time. I added a getlasterror call right after it and it returns ERROR_ALREADY_EXISTS :/
Here's my code:
WaitForMutexToLeave:
; Make sure only one copy runs.
invoke CreateMutexA,0,0,ADDR MutexString ; try to create the mutex
test eax,eax ; No copies running yet?
jz BeginProc ; Start the process
invoke OpenMutexA,\
01F0001h,\ ; (MUTEX_ALL_ACCES)
TRUE,\ ; Do inherit
ADDR MutexString ; Mutex String
invoke GetLastError
cmp eax,WAIT_ABANDONED ; Is the other process dead?
jz BeginProc ; If yes, start the process
invoke Sleep,100
jmp WaitForMutexToLeave
BeginProc:
...
I have no clue why it wont work, it seems perfectly logical :/
Hi,
You should use SetLastError after the CreateMutex in order to determine if there is an actual error when OpenMutex is executed otherwise you simply get the error from CreateMutex. However, I think I may have misunderstood the explanation since it is a problem I never deal with, as in the first response you should be using one of the wait functions, it is those functions that return the WAIT_ABANDONED error code. So your code would look something like this...
WaitForMutexToLeave:
; Make sure only one copy runs.
invoke CreateMutexA,0,0,ADDR MutexString ; try to create the mutex
test eax,eax ; No copies running yet?
jz BeginProc ; Start the process
invoke OpenMutexA,\
01F0001h,\ ; (MUTEX_ALL_ACCES)
TRUE,\ ; Do inherit
ADDR MutexString ; Mutex String
invoke WaitForSingleObject, eax, -1
invoke GetLastError
cmp eax,WAIT_ABANDONED ; Is the other process dead?
jnz WaitForMutexToLeave ; If not, restart the wait
; invoke Sleep,100
; jmp WaitForMutexToLeave
BeginProc:
No need for the loop which only eats up processor slices anyway, Try it, it might work.
Donkey
Thanks donkey, problem solved!
Here's the code for anyone that wants it:
; A message box will be displayed. When you close it,
; the app will be destroyed allowing another copy to begin its work
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
mutexName db "Global\TEST"
hMutex dd 0
.code
start:
WaitForMutexToLeave:
invoke CreateMutexA,0,0,ADDR mutexName ; try to create the mutex
test eax,eax ; No copies running yet?
je BeginProc ; Start the process
invoke OpenMutexA,\
01F0001h,\ ; (MUTEX_ALL_ACCES)
TRUE,\ ; Do inherit
ADDR mutexName ; Mutex String
mov [hMutex],eax ; save the handle
invoke WaitForSingleObject, eax, -1
cmp eax,WAIT_ABANDONED ; Is the other process dead?
je BeginProc ; If not, restart the wait
push dword ptr [hMutex]
call CloseHandle
jmp WaitForMutexToLeave
BeginProc:
push dword ptr [hMutex]
call CloseHandle
invoke MessageBox,0,0,0,0
invoke ExitProcess,0
end start
I've never had this much trouble coding anything, so I hope someone on the internet finds this useful :)