Why is mutex not freed upon deletion?

I have the following code:

using (Mutex mut = new Mutex(false, MUTEX_NAME)) { if (mut.WaitOne(new TimeSpan(0, 0, 30))) { // Some code that deals with a specific TCP port // Don't want this to run at the same time in another process } } 

I set a breakpoint in the if block and ran the same code in another instance of Visual Studio. As expected, .WaitOne call .WaitOne . However, to my surprise, as soon as I continue in the first instance and the using block completes, I get an exception in the second process about the abandoned Mutex.

The fix is ​​to call ReleaseMutex :

 using (Mutex mut = new Mutex(false, MUTEX_NAME)) { if (mut.WaitOne(new TimeSpan(0, 0, 30))) { // Some code that deals with a specific TCP port // Don't want this to run twice in multiple processes } mut.ReleaseMutex(); } 

Now everything works as expected.

My question is: Usually the IDisposable point clears any state into which you insert things. Perhaps I have several expectations and releases in the using block, but when the Mutex handle is located, should it not be automatically released? In other words, why do I need to call ReleaseMutex if I'm in a using block?

I am also concerned that if the code inside the if block crashes, I will remain mutexes lying around.

Is there any use for placing Mutex in a using block? Or, should I just update the Mutex instance, wrap it in try / catch and call ReleaseMutex() in the finally block (basically implement what I thought Dispose() )

+48
c # mutex
Aug 21 '14 at 17:40
source share
9 answers

The documentation explains (in the "Remarks" section) that there is a conceptual difference between an instance of a Mutex object (which actually does nothing special for synchronization) and acquires Mutex (using WaitOne ). Note:

  • WaitOne returns a boolean value, meaning that receiving a Mutex may fail (timeout), and both cases must be handled
  • When WaitOne returns true , then the calling thread has acquired Mutex and should call ReleaseMutex , otherwise Mutex will stop
  • When it returns false , then the calling thread should not call ReleaseMutex

So there is more to mutexes than to instantiate. As for whether using should be used anyway, let's see what Dispose does (as inherited from WaitHandle ):

 protected virtual void Dispose(bool explicitDisposing) { if (this.safeWaitHandle != null) { this.safeWaitHandle.Close(); } } 

As we can see, Mutex is not released, but there is some kind of cleanup, so sticking with using would be a good approach.

As for how you should act, you can, of course, use the try/finally block to make sure that if Mutex is received, it gets properly released. This is perhaps the easiest approach.

If you really don't like the case where Mutex cannot be obtained (which you did not specify, since you are passing the TimeSpan to WaitOne ), you can wrap Mutex in your own class that implements IDisposable , gets Mutex in the constructor (using WaitOne() without arguments) and release it inside Dispose . Although, probably, I would not recommend this, as this will cause your threads to wait indefinitely if something goes wrong, and despite the fact that there are good reasons for explicitly handling both cases when trying to acquire as pointed out by @HansPassant.

+49
Aug 21 '14 at 18:13
source share

This design decision was made a long, long time ago. More than 21 years ago, long before the advent of .NET, or the semantics of IDisposable were ever considered. The .NET Mutex class is a wrapper class for basic operating system support for mutexes. The pinvokes constructor of CreateMutex, the WaitOne () method throws WaitForSingleObject () .

Note the WAIT_ABANDONED value returned by WaitForSingleObject (), which throws an exception.

Windows designers set a solid rule in which the thread to which the mutex belongs must call ReleaseMutex () before it exits. And if this does not mean that it is a very strong indication that the thread unexpectedly terminated, usually through an exception. This means that synchronization is lost, a very serious problem with threads. Compare with Thread.Abort (), a very dangerous way to interrupt a thread in .NET for the same reason.

.NET developers did not modify this behavior in any way. Last but not least, because there is no way to check the state of a mutex other than to wait. You must call ReleaseMutex (). And note that your second snippet is not correct; you cannot call it a mutex that you did not receive. It must be moved inside the body of the if () operator.

+33
Aug 21 '14 at 18:40
source share

Ok, posting the answer to my own question. From what I can say, this is an ideal way to implement Mutex , which:

  • Always gets Disposed
  • Received iff WaitOne .
  • It will not be denied if any code throws an exception.

Hope this helps someone!

 using (Mutex mut = new Mutex(false, MUTEX_NAME)) { if (mut.WaitOne(new TimeSpan(0, 0, 30))) { try { // Some code that deals with a specific TCP port // Don't want this to run twice in multiple processes } catch(Exception) { // Handle exceptions and clean up state } finally { mut.ReleaseMutex(); } } } 

Update:. Some may argue that if the code in a try block puts your resource in an unstable state, you should not let go of Mutex and instead leave it abandoned. In other words, just call mut.ReleaseMutex(); when the code succeeds, and do not put it in the finally block. Code acquiring Mutex could catch this exception and do the right thing.

In my situation, I do not change any state. I am temporarily using a TCP port and cannot start another instance of the program at the same time. For this reason, I think my solution above is fine, but yours may be different.

+7
Aug 21 '14 at 18:28
source share

One of the main applications of the mutex is to ensure that the only code that ever sees a shared object in a state that does not satisfy its invariants is a code that (hopefully temporarily) puts the object in this state. The normal template for the code that should change the object:

  • Getting a Mutex
  • Make changes to the object, due to which its state becomes invalid.
  • Make changes to the object, which causes its state to become valid again.
  • Disabling a Mutex

If something goes wrong after No. 2 has begun and before No. 3 has finished, the object can be left in a state that does not satisfy its invariants. Since the correct template is to free the mutex before deleting it, the fact that the code provides the mutex without releasing it means that something went wrong. Thus, it may be unsafe to enter the code in the mutex (since it has not yet been released), but there is no reason to wait for the mutex to exit (because - if it was deleted, it will never be), so the correct course of action is an exception.

A template that is slightly better than the one implemented by the mutex.NET object is to use the acquire method to return an IDisposable that does not encapsulate the mutex, but rather receive it privately. Disposal of this object will result in cancellation of the mutex. The code might look something like this:

 using(acq = myMutex.Acquire()) { ... stuff that examines but doesn't modify the guarded resource acq.EnterDanger(); ... actions which might invalidate the guarded resource ... actions which make it valid again acq.LeaveDanger(); ... possibly more stuff that examines but doesn't modify the resource } 

If the internal code fails between EnterDanger and LeaveDanger , then the collection object must invalidate the mutex by calling Dispose on it, since the protected resource may be in a damaged state. If the internal code fails in another place, the mutex must be freed, since the protected resource is in a valid state, and the code in the using block will no longer be needed. I don’t have any specific recommendations from libraries implementing this template, but it’s not particularly difficult to implement as a wrapper around other types of mutex.

+7
Aug 21 '14 at 20:36 on
source share

We need to understand more .net in order to know what is happening at the top of the MSDN page, giving the first hint that someone is "weird" going on:

synchronization primitive, which can also be used for interprocess synchronization.

Mutex is a Win32 " Named Object ", each process blocks it by name , a .net object is just the shell of a round of Win32 calls. Muxtex itself lives in the address space of Windows Kernal, and not in the address space of your application.

In most cases, you are better off using Monitor if you are only trying to synchronize access to objects in a single process.

+4
Aug 21 '14 at 18:44
source share

If you need to ensure that the mutex is released, switch to the finally try catch block and put the mutex release in the finally block. It is assumed that you own and have a handle for the mutex. This logic must be enabled before calling release.

+3
Aug 21 '14 at 5:55
source share

Reading the documentation for ReleaseMutex , it seems like the design was that Mutex should be released consciously. if ReleaseMutex not called, it means that the protected partition is abnormal. final release or destruction, bypasses this mechanism. you can still ignore the AbandonedMutex exception of course.

+2
Aug 21 '14 at 18:03
source share

Be aware: Mutex.Dispose (), executed by the Garbage collector, fails because the garbage collection process does not own the handle according to Windows.

+2
Sep 28 '15 at 14:41
source share

Dispose dependent on WaitHandle . Thus, even if using invokes Dispose , it will not go into effect until the stable condition is met. When you call ReleaseMutex , you tell the system that you are freeing the resource, and thus it can freely dispose of it.

+1
Aug 21 '14 at 17:51 on
source share



All Articles