How to gracefully get out of AbandonedMutexException? - c#

I use the following code to synchronize mutually exclusive access to a shared resource between several running processes.
The mutex is created as such:
Mutex mtx = new Mutex(false, "MyNamedMutexName");
Then I use this method to enter mutually exclusive section:
public bool enterMutuallyExclusiveSection()
{
//RETURN: 'true' if entered OK,
// can continue with mutually exclusive section
bool bRes;
try
{
bRes = mtx.WaitOne();
}
catch (AbandonedMutexException)
{
//Abandoned mutex, how to handle it?
//bRes = ?
}
catch
{
//Some other error
bRes = false;
}
return bRes;
}
and this code to leave it:
public bool leaveMutuallyExclusiveSection()
{
//RETURN: = 'true' if no error
bool bRes = true;
try
{
mtx.ReleaseMutex();
}
catch
{
//Failed
bRes = false;
}
return bRes;
}
But what happens is that if one of the running processes crashes, or if it is terminated from a Task Manager, the mutex may return AbandonedMutexException exception. So my question is, what is the graceful way to get out of it?
This seems to work fine:
catch (AbandonedMutexException)
{
//Abandoned mutex
mtx.ReleaseMutex();
bRes = mtx.WaitOne();
}
But can I enter the mutually exclusive section in that case?
Can someone clarify?

According to MSDN the AbandonedMutexException is:
The exception that is thrown when one thread acquires a Mutex object
that another thread has abandoned by exiting without releasing it.
This means that the thread in which this exception was thrown is the new owner of the Mutex (otherwise calling the Mutex.ReleaseMutex Method like you're doing would trigger an ApplicationException), and if you can assure the integrity of the data structures protected by the mutex you can simply ignore the exception and continue executing your application normally.
However, most of the times the AbandonedMutexException is raised the integrity of the data structures protected by the mutex cannot be guaranteed, and that's why this exception was introduced in the version 2.0 of the .NET framework:
An abandoned mutex indicates a serious programming error. When a
thread exits without releasing the mutex, the data structures
protected by the mutex might not be in a consistent state. Prior to
version 2.0 of the .NET Framework, such problems were hard to discover
because no exception was thrown if a wait completed as the result of
an abandoned mutex.

Related

Empty try {}, no catch, filled finally{} in System.Diagnostics.Process sources - what is it good for? [duplicate]

I noticed in System.Threading.TimerBase.Dispose() the method has a try{} finally{} block but the try{} is empty.
Is there any value in using try{} finally{} with an empty try?
http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Dispose(WaitHandle notifyObject)
{
bool status = false;
bool bLockTaken = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
}
finally {
do {
if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) {
bLockTaken = true;
try {
status = DeleteTimerNative(notifyObject.SafeWaitHandle);
}
finally {
m_lock = 0;
}
}
Thread.SpinWait(1);
// yield to processor
}
while (!bLockTaken);
GC.SuppressFinalize(this);
}
return status;
}
From http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/:
This methodology guards against a
Thread.Abort call interrupting the
processing. The MSDN page of
Thread.Abort says that “Unexecuted
finally blocks are executed before the
thread is aborted”. So in order to
guarantee that your processing
finishes even if your thread is
aborted in the middle by someone
calling Abort on your thread, you can
place all your code in the finally
block (the alternative is to write
code in the “catch” block to determine
where you were before “try” was
interrupted by Abort and proceed from
there if you want to).
This is to guard against Thread.Abort interrupting a process. Documentation for this method says that:
Unexecuted finally blocks are executed before the thread is aborted.
This is because in order to recover successfully from an error, your code will need to clean up after itself. Since C# doesn't have C++-style destructors, finally and using blocks are the only reliable way of ensuring that such cleanup is performed reliably. Remember that using block turns into this by the compiler:
try {
...
}
finally {
if(obj != null)
((IDisposable)obj).Dispose();
}
In .NET 1.x, there was a chance that finally block will get aborted. This behavior was changed in .NET 2.0.
Moreover, empty try blocks never get optimized away by the compiler.

What happens if I Monitor.Enter conditionally while another thread is in the critical section without a lock?

I'm attempting to reimplement functionality from a system class (Lazy<T>) and I found this unusual bit of code. I get the basic idea. The first thread to try for a value performs the calculations. Any threads that try while that's happening get locked at the gate, wait until release, and then go get the cached value. Any later calls notice the sentinel value and don't bother with the locks any more.
bool lockWasTaken = false;
var obj = Volatile.Read<object>(ref this._locker);
object returnValue = null;
try
{
if (obj != SENTINEL_VALUE)
{
Monitor.Enter(obj, ref lockWasTaken);
}
if (this.cachedValue != null) // always true after code has run once
{
returnValue = this.cachedValue;
}
else //only happens on the first thread to lock and enter
{
returnValue = SomeCalculations();
this.cachedValue = returnValue;
Volatile.Write<object>(ref this._locker, SENTINEL_VALUE);
}
return returnValue
}
finally
{
if (lockWasTaken)
{
Monitor.Exit(obj);
}
}
But let's say, after a change in the code, that another method resets the this._locker to it's original value and then goes in to lock and recalculate the cached value. While it does this, another thread happened to be picking up the cached value, so it's inside the locked section, but without a lock. What happens? Does it just execute normally while the thread with the lock also goes in parallel?
While it does this, another thread happened to be picking up the cached value, so it's inside the locked section, but without a lock. What happens? Does it just execute normally while the thread with the lock also goes in parallel?
Yes, it'll just execute normally.
That being said, this code appears like it could be removed entirely by using Lazy<T>. The Lazy<T> class provides a thread safe way to handle lazy instantiation of data, which appears to be the goal of this code.
Basically, the entire code could be replaced by:
// Have a field like the following:
Lazy<object> cachedValue = new Lazy<object>(() => SomeCalculations());
// Code then becomes:
return cachedValue.Value;

IOException getting thrown by ReaderWriteLockSlim?

I have a static class which is accessed by multiple threads and uses a ReaderWriterLockSlim in various methods to maintain thread safety. This works fine most of the time, however very intermittently I'm seeing an IOException handle is invalid error being thrown by one particular method as shown in the stack trace below. This has me greatly confused as I didn't even know that System.IO was involved in a ReaderWriterLock.
Any help at all in understanding where the error may be comming from would be greatly appreciated.
Stack Trace:
System.IO.IOException: The handle is invalid.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle.Reset()
at System.Threading.ReaderWriterLockSlim.WaitOnEvent(EventWaitHandle waitEvent, UInt32& numWaiters, Int32 millisecondsTimeout)
at System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLock(Int32 millisecondsTimeout)
Code:
class Class1
{
private static ReaderWriterLockSlim readwriteLock = new ReaderWriterLockSlim();
private const int readwriterlocktimeoutms = 5000;
private static void myMethod(int ID)
{
bool IsTaken = false;
bool isWriteLockTaken = false;
if (!readwriteLock.TryEnterUpgradeableReadLock(readwriterlocktimeoutms))
{
throw new Exception("SafeGetSuItem: Error acquiring read lock");
}
else { IsTaken = true; }
try
{
// do some work which may require upgrading to a write lock depending on particular conditions
}
finally
{
if (IsTaken)
{
try
{
readwriteLock.ExitUpgradeableReadLock();
IsTaken = false;
}
catch
{
throw;
}
}
}
}
}
enter code here
bool IsWriteTaken = false;
try
{
if (!readerwriterlock.TryEnterWriteLock(readerwriterlocktimeout))
{
// log the error
}
else
{
IsWriteTaken = true;
}
if (IsWriteTaken)
{
// do some work
}
}
finally
{
if (IsWriteTaken)
{
try
{
readerwriterlock.ExitWriteLock();
}
catch
{
throw;
}
}
}
This is a little weird. You may have stumbled upon a bug in the WaitHandle class. I picked this apart via Reflector and this is what I am seeing.
Calling Dispose on the ReaderWriterLockSlim will call Close on the EventWaitHandle listed in the stack trace.
Calling Close on a EventWaitHandle attempts to dispose the underlying SafeHandle.
Calling Reset on a EventWaitHandle calls directly into the ResetEvent Win32 API from kernel32.dll and passes in the SafeHandle.
I see no synchronization mechanisms in place that prevent a race between the disposing of a SafeHandle and having that instance consumed by the Win32 API.
Are you calling Dispose on the ReaderWriterLockSlim instance from another thread while TryEnterUpgradeableReadLock could be executing? This seems like the most likely scenario to me. Actually, this is the only scenario that I am seeing that would lead to an IOException being thrown.
It seems to me, based solely on my cursory analysis of the BCL code, that the IOException could be by-design, but it would make a whole lot more sense if Microsoft could somehow generate a ObjectDisposedException instead which happens on every single other attempt I have made to reproduce the problem. I would go ahead and report this to Microsoft.

ASP.NET lock thread method

I'm developing an ASP.NET forms webapplication using C#. I have a method which creates a new Order for a customer. It looks similar to this;
private string CreateOrder(string userName) {
// Fetch current order
Order order = FetchOrder(userName);
if (order.OrderId == 0) {
// Has no order yet, create a new one
order.OrderNumber = Utility.GenerateOrderNumber();
order.Save();
}
return order;
}
The problem here is, it is possible that 1 customer in two requests (threads) could cause this method to be called twice while another thread is also inside this method. This can cause two orders to be created.
How can I properly lock this method, so it can only be executed by one thread at a time per customer?
I tried;
Mutex mutex = null;
private string CreateOrder(string userName) {
if (mutex == null) {
mutex = new Mutex(true, userName);
}
mutex.WaitOne();
// Code from above
mutex.ReleaseMutex();
mutex = null;
return order;
}
This works, but on some occasions it hangs on WaitOne and I don't know why. Is there an error, or should I use another method to lock?
Thanks
Pass false for initiallyOwned in the mutex ctor. If you create the mutex and initially own it, you need to call ReleaseMutex again.
You should always try finally when releasing mutex. Also, make sure that the key is correct(userName)
Mutex mutex = null;
private string CreateOrder(string userName) {
mutex = mutex ?? new Mutex(true, userName);
mutex.WaitOne();
try{
// Code from above
}finally{
mutex.ReleaseMutex();
}
mutex = null;
return order;
}
In your code, you are creating the mutex lazily. This leads to race conditions.
E.g. it can happen that the mutex is only partially constructed when you call WaitOne() from another thread.
It can also happen that you create two mutex instances.
etc...
You can avoid this by creating the instance eagerly - i.e. as in Michael's code.
(Be sure to initialize it to a non-owned state.)
Mutex is a kernel-level synchronization primitive - it is more expensive than Monitor (that is what lock uses.).
Unless I'm missing something, can't you just use a regular lock?
private object _locker = new object();
private string CreateOrder(string userName)
{
lock(_locker)
{
// Fetch current order
Order order = FetchOrder(userName);
if (order.OrderId == 0)
{
// Has no order yet, create a new one
order.OrderNumber = Utility.GenerateOrderNumber();
order.Save();
}
return order;
}
}
I have always avoided locking in a web-based application - let the web server deal with the threads, and instead build in duplicate detection.
What do you think you're going to get by locking on the CreateOrder? It seems to me that you may avoid creating two order simultaneously, but you're still going to end up with two orders created.
Its easier to do this:
define a class somewhere like so:
public class MyLocks {
public static object OrderLock;
static MyLocks() {
OrderLock = new object();
}
}
then when using the lock do this:
lock(MyLocks.OrderLock) {
// put your code here
}
Its not very complicated then. Its light weight to define locks for whatever purpose as they are just very tiny objects in memory that are alive across multiple threads.

Why use try {} finally {} with an empty try block?

I noticed in System.Threading.TimerBase.Dispose() the method has a try{} finally{} block but the try{} is empty.
Is there any value in using try{} finally{} with an empty try?
http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Dispose(WaitHandle notifyObject)
{
bool status = false;
bool bLockTaken = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
}
finally {
do {
if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) {
bLockTaken = true;
try {
status = DeleteTimerNative(notifyObject.SafeWaitHandle);
}
finally {
m_lock = 0;
}
}
Thread.SpinWait(1);
// yield to processor
}
while (!bLockTaken);
GC.SuppressFinalize(this);
}
return status;
}
From http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/:
This methodology guards against a
Thread.Abort call interrupting the
processing. The MSDN page of
Thread.Abort says that “Unexecuted
finally blocks are executed before the
thread is aborted”. So in order to
guarantee that your processing
finishes even if your thread is
aborted in the middle by someone
calling Abort on your thread, you can
place all your code in the finally
block (the alternative is to write
code in the “catch” block to determine
where you were before “try” was
interrupted by Abort and proceed from
there if you want to).
This is to guard against Thread.Abort interrupting a process. Documentation for this method says that:
Unexecuted finally blocks are executed before the thread is aborted.
This is because in order to recover successfully from an error, your code will need to clean up after itself. Since C# doesn't have C++-style destructors, finally and using blocks are the only reliable way of ensuring that such cleanup is performed reliably. Remember that using block turns into this by the compiler:
try {
...
}
finally {
if(obj != null)
((IDisposable)obj).Dispose();
}
In .NET 1.x, there was a chance that finally block will get aborted. This behavior was changed in .NET 2.0.
Moreover, empty try blocks never get optimized away by the compiler.

Categories

Resources