Page 1 of 1
UnlockMutex w/o Lock locks
Posted: Wed May 06, 2009 12:58 pm
by Polly
UnlockMutex w/o previous Lock locks the mutex. Even a following Unlock can't unlock it again.
I know that this is not the normal process, but I think this behaviour is rather unexpected and causes unneccessary difficulties - you must make sure that in any case a lock has been set previously or your pgm is hanging.
Code: Select all
mut=CreateMutex()
Debug UnlockMutex(mut)
Debug LockMutex(mut)
Debug UnlockMutex(mut)
Tested on XP, 4.30
Posted: Wed May 06, 2009 1:03 pm
by Fred
You can't use it like that without border effects. It's a raw API call, so it's the 'normal' behavior on Windows. The doc will be updated to reflect this.
Posted: Wed May 06, 2009 1:17 pm
by Polly
And you can't bypass this "normal Windows behaviour" by maintaining an index whether this mutex is in a lock or not? Of course I can do this in my application, but I would rather see this as a service from PB. One unlock too much and the pgm is hanging - that's a very nasty behaviour.
Posted: Wed May 06, 2009 1:32 pm
by freak
> One unlock too much and the pgm is hanging - that's a very nasty behaviour.
If this happens then you have a serious bug in your program logic. Its not PB's job to correct that.
Posted: Wed May 06, 2009 1:59 pm
by Polly
Yes, I have a bug - and you a bug-prone interface design ...
I think, this could easily be avoided.
Posted: Wed May 06, 2009 1:59 pm
by Trond
There should be a debugger check for this, else it would be hard to know where the bug is, since when the program hangs in LockMutex() the debugger's "stop" command doesn't work.
Posted: Wed May 06, 2009 2:38 pm
by freak
Polly wrote:Yes, I have a bug - and you a bug-prone interface design ...
I think, this could easily be avoided.
Mutexes are there to protect critical resources from being accessed by two threads. What good is that if you don't even know wether your resource is currently locked or not ?
If PB "fixed" this error you would gain nothing. Your program wouldn't hang, but still whatever the mutex was protecting is now in an inconsistent state. If you are unlucky you end up corrupting your program data. I'd prefere a hanging program in that case. There is no sense in "fixing" problems for the programmer when all it does is lead to potentially more dangerous problems.
Besides that, "easily avoided" is not quite right. Things are no as easy as some people might think, especially when it comes to threads.
@Trond:
I'll try to add a check for that.
Posted: Wed May 06, 2009 3:30 pm
by Polly
I used this Unlock to make sure that at a given point the resource was unlocked, regardless what happened before. I find this a quite reasonable approch and cannot see where the problem should be when Unlock always would do what it says.
I found a workaround now - just put a TryLock before - but I think there will be others that will fall into this trap. However it should be easy for you to fix the problem based on that.
BTW: The command TryLock is only senseful "if you don't even know wether your resource is currently locked or not"
Posted: Thu May 14, 2009 3:29 am
by Rescator
You are in danger of making mutex useless by the way you are thinking/coding.
Code: Select all
mut=CreateMutex()
;The next code is someplace else in the program.
This is the proper way to check for a lock, while not blocking the thread.
If TryLockMutex(mut)
Debug "Was not locked"
;Do some stuff here if needed.
Debug UnlockMutex(mut)
Else
Debug "Was locked"
;Nothing we can do, attempting to unlock here would be pointless
;as in a multi-threaded app it is possible that it's been unlocked already
;by the time this Else block is executed.
;However if this in the cleanup routine of your program,
;AND it is the very last time the mutex is referenced,
;AND all other threads using the mutex has finished,
;THEN you could do a unlock, but only then.
;PS! "A mutex can only be unlocked by the thread that also locked it. " so you need to trigger the cleanup in the thread that made the lock.
EndIf
Polly wrote:BTW: The command TryLock is only senseful "if you don't even know wether your resource is currently locked or not"
Actually no, it's purpose is to allow doing stuff if nothing else is doing stuff.
If Try fails it means something else is busy doing stuff.
LockMutex() is a blocking wait.
TryLockMutex() let you do "other" stuff, or implement you own wait loop.
TryLock is used a lot in parallel processing for example.
Posted: Thu May 14, 2009 9:40 am
by Trond
Polly wrote:I found a workaround now - just put a TryLock before - but I think there will be others that will fall into this trap. However it should be easy for you to fix the problem based on that.
BTW: The command TryLock is only senseful "if you don't even know wether your resource is currently locked or not"
You forgot to take into consideration that UnlockMutex() is only useful if the current thread holds the lock (which you should know), while TryLockMutex() is for the cases where you don't know if
other threads are holding the lock. TryLockMutex() is not meant to help you know whether the current thread holds the lock.
Posted: Sun May 17, 2009 10:14 am
by Polly
So much arguments, only to justify that an Unlock must do the opposite of what it says in certain cases? Very strange....
Posted: Sun May 17, 2009 11:03 am
by Trond
Polly wrote:So much arguments, only to justify that an Unlock must do the opposite of what it says in certain cases? Very strange....
The help says that UnlockMutex() unlocks a mutex previously locked in the same thread by LockMutex(). If it doesn't work like that it's a bug (but it does work like that).
Calling UnlockMutex() without LockMutex() is like calling CloseWindow() without OpenWindow() or FreeMemory() without AllocateMemory() or PlaySound() without LoadSound(). It's obvious that it won't work.