Why Doesn't Mutex Get Released When Disposed

Why doesn't Mutex get released when disposed?

The documentation explains (in the "Remarks" section) that there is a conceptual difference between instantiating a Mutex object (which does not, in fact, do anything special as far as synchronization goes) and acquiring a Mutex (using WaitOne). Note that:

  • WaitOne returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
  • When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
  • When it returns false, then the calling thread must not call ReleaseMutex

So, there's more to Mutexes than instantiation. As for whether you should use using anyway, let's take a look at what Dispose does (as inherited from WaitHandle):

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

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

As to how you should proceed, you can of course use a try/finally block to make sure that, if the Mutex is acquired, that it gets properly released. This is likely the most straightforward approach.

If you really don't care about the case where the Mutex fails to be acquired (which you haven't indicated, since you pass a TimeSpan to WaitOne), you could wrap Mutex in your own class that implements IDisposable, acquire the Mutex in the constructor (using WaitOne() with no arguments), and release it inside Dispose. Although, I probably wouldn't recommend this, as this would cause your threads to wait indefinitely if something goes wrong, and regardless there are good reasons for explicitly handling both cases when attempting an acquire, as mentioned by @HansPassant.

Why don't named .NET mutexes throw AbandonedMutexException when disposed?

You probably don't want it to work the way that you suggest. Let's say you have this:

using (var m = new Mutex(....))
{
m.WaitOne();
// do some stuff here
// that ends up throwing an exception
}

The exception is thrown while your thread holds the mutex. If the mutex were released as part of the dispose, then some other thread could obtain the mutex and begin partying on the data that you were updating. Except that now the data is in an unknown (probably inconsistent or corrupt) state.

It's best, of course, to handle the exception and clean things up, but absent that I'd rather the mutex remain held (or abandoned if the thread dies) so that the next thread that tries to acquire the mutex knows that something bad happened.

In addition to the above, adding automatic release would require that the .NET wrapper keep track of which thread owns the mutex. And the Dispose method would have to check that value to determine if it should call ReleaseMutex. And it's just not possible to keep track of that. The .NET program could pass the mutex handle to some unmanaged code, which could acquire or release the mutex without the wrapper's knowledge.

So, the answer is twofold: First, it's not possible. Second, even if it were possible, you probably don't want that behavior.

Why am I getting a newly created Mutex if I am reusing an existing one in the following code?

Because mutex is destoyed when last handle to it is closed (reference):

Use the CloseHandle function to close the handle. The system closes
the handle automatically when the process terminates. The mutex object
is destroyed when its last handle has been closed.

That's what happens in your example - you create mutex and then (with using) close the only handle to it, so it is destroyed.

Note that you should not create mutex like this and close handle to it without releasing mutex anyway:

Mutex mutex = new Mutex(true, "Global\\AAA", out createdNew)

This says - if mutex does not already exists, create it and give this thread ownership of it. So if createdNew is true after this call - you own this mutex and so should release it. By closing handle you either just destoy mutex (but that is useless scenario), or abandon mutex, so that other threads\processes waiting on that mutex with throw AbandonedMutexException. So it should be:

using (Mutex mutex = new Mutex(true, "Global\\AAA", out createdNew)) {
if (!createdNew) {
throw new InvalidOperationException();
}
// do something useful
mutex.ReleaseMutex();
}

Second using is also not correct:

Mutex mutex = new Mutex(false, "Global\\AAA", out createdNew)

By passing false as first parameter you say: whether this mutex already exists or not - do not give this thread ownership of it. Then you do:

if (!createdNew)
{
mutex.ReleaseMutex();
}

But you cannot own mutex anyway at this point, so even if control flow entered this if block - it would not work anyway (throw exception on ReleaseMutex). Instead you should explicitly call WaitOne and ignore result of createdNew (is not relevant in this case):

using (Mutex mutex = new Mutex(false, "Global\\AAA")) {
if (mutex.WaitOne()) {
// do something useful
mutex.ReleaseMutex();
}
}

what happens to a mutex object if not released by parent applicaiton

According to the documentation, it is abandoned (not necessarily disposed)

If a thread terminates while owning a mutex, the mutex is said to be abandoned

Also, heed the warning about abandoned Mutexes:

An abandoned mutex often indicates a serious error in the code. When a thread exits without releasing the mutex, the data structures protected by the mutex might not be in a consistent state. The next thread to request ownership of the mutex can handle this exception and proceed, if the integrity of the data structures can be verified.

Should I dispose a Mutex?

A mutex is a Windows kernel object (here wrapped in a .NET object).

As such, it is an unmanaged resource that should be disposed.

More accurately, the .NET object contains a HANDLE to the mutex, which must be released/disposed of somehow.

I don't trust that code sample in the Mutex class docs where the mutex object is not disposed. Although Henzi has a good point in comment: The Mutex object is static and would be either disposed by the finalizer or destroyed by the Windows kernel when the process exits.

Also, note that Close() disposes the object as well.

Of course, there's nothing wrong with keeping an existing Mutex object in your app even while you don't use it. They are light resources.

Is a Try-Finally-Release redundant while using a Mutex 'using'?

The code run when Dispose method is called is:

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

The one executed by ReleaseMutex is:

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public void ReleaseMutex()
{
if (!Win32Native.ReleaseMutex(base.safeWaitHandle))
{
throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException"));
}
Thread.EndCriticalRegion();
Thread.EndThreadAffinity();
}

So your code isn't redundant

Exception when releasing a Mutex. What could cause this?

Move the WaitOne() call above the try block. You only want to release the mutex when you know you acquired it.

You'll now also stand a chance to get a better diagnostic.

C# Mutex always stuck on WaitOne

I think if you create the mutex with true (new Mutex(true, "req_mutex");)
you so should not need to call WaitOne() in that process.

The documentation says it is better to specify false for initiallyOwned when calling this constructor overload. https://msdn.microsoft.com/en-us/library/f55ddskf(v=vs.110).aspx

EDIT: ahh, you beat me to it :) ...



Related Topics



Leave a reply



Submit