Monitor.TryEnter / Monitor.Exit and SynchronizationLockException - c#

Is it possible to detect if the same thread trying to release the lock?
We have many places in code that looks like:
try
{
try
{
if(!Monitor.TryEnter(obj, 2000))
{
throw new Exception("can not lock");
}
}
finally
{
Monitor.Exit(obj);
}
}
catch
{
//Log
}
The above code very simplified, and actually Enter and Exit statement located in custom object (lock manager).
The problem, that in that structure, we have SynchronizationLockException when trying to "Exit", since it looks like the thread that not succeed to lock, tries to release in finally.
So the question, is how I can know if the thread who making Monitor.Exit is the same thread who did Monitor.Enter?
I thought that I can use CurrentThread.Id to sync enter and exit, but I'm not sure if it "safe" enough.

So the question, is how I can know if the thread who making Monitor.Exit is the same thread who did Monitor.Enter?
You can't, easily, as far as I'm aware. You can't find out which thread owns a monitor.
However, this is just a coding issue - you should change your code so that it doesn't even attempt to release the monitor when it shouldn't. So your code above could be rewritten as:
if (!Monitor.TryEnter(obj, 2000))
{
throw new Exception(...);
}
try
{
// Presumably other code
}
finally
{
Monitor.Exit(obj);
}
Or even better, if you're using .NET 4, use the overload of TryEnter which accepts an ret parameter:
bool gotMonitor = false;
try
{
Monitor.TryEnter(obj, ref gotMonitor);
if (!gotMonitor)
{
throw new Exception(...);
}
// Presumably other code
}
finally
{
if (gotMonitor)
{
Monitor.Exit(obj);
}
}

As you think that to put the calling of Monitor.Exit in try-catch was 'durty'(dirty?), here's a very simple idea trying to 'take the durty away'. Lock is reentrant for the same thread and if one thread acquired successfully, before it releases, attempt from another thread will fail. So that you can consider something like:
public void Exit(object key) {
if(!IsActive) {
return;
}
if(LockDictionary.ContainsKey(key)) {
var syncObject=LockDictionary[key];
if(Monitor.TryEnter(syncObject.SyncObject, 0)) {
SetLockExit(syncObject);
Monitor.Exit(syncObject.SyncObject);
Monitor.Exit(syncObject.SyncObject);
}
}
}
We call Monitor.Exit twice because we lock it twice, one in the code outer, and one just here.

I know this is an older question, but here's my answer anyway.
I would move the try-finally construct inside the if:
try
{
if(Monitor.TryEnter(obj, 2000))
{
try
{
// code here
}
finally
{
Monitor.Exit(obj);
}
}
else
{
throw new Exception("Can't acquire lock");
}
}
catch
{
// log
}

Related

Why does deadlock occur on calling Semaphore.WaitOne?

The run() function in the following code is called from other threads simultaneously. At anytime, on any line, a ThreadAbortException might occur according to the general design of the application, which I cannot change.
I sometimes get SemaphoreFullException while calling pool.Release(). I think this occurs if a thread abort exception occurs while calling "pool.WaitOne()". During my debug tries, after SemaphoreFullException has occurred, there is no problem in running the code. After that exception, pool.WaitOne() calls and other things work just as expected.
I haven't been able to get a deadlock situation during my local debug sessions. However, in a remote computer, I have a deadlock with this code. I attach that process using remote debugger and see that the execution is locked on the line pool.WaitOne();.
I can't figure out how this would happen, and what I'm doing wrong. Any help is very appreciated.
private static object poolLocker = new object();
private static Semaphore _pool;
private static Semaphore pool
{
get
{
if (_pool == null)
lock (poolLocker)
if (_pool == null)
{
int count = myMaximumThreadCount;
_pool = new Semaphore(count, count);
}
return _pool;
}
}
private void run()
{
try
{
pool.WaitOne();
do_something_that_may_throw_exception();
}
finally
{
try
{
pool.Release();
}
catch (SemaphoreFullException) { }
}
}
Try to change the initialization of the semaphore object in pool property to:
private static Semaphore pool
{
get
{
if (_pool == null)
lock (poolLocker)
if (_pool == null)
{
int count = myMaximumThreadCount;
_pool = new Semaphore(0, count);
}
return _pool;
}
}
An initial count for this semaphore should be set to zero.
I have found the cause of the deadlock; and it has nothing to do with the question I've asked, so this is a bad question, sorry for that. There seems to be no problem in the code in the question.
The cause: In the do_something_that_may_throw_exception() function, an extern function of a C++ library is being called. When an error occurs in the C++ function, a SEHException is thrown. However, in my tries this exception can only be caught in a function that has HandleProcessCorruptedStateExceptions and SecurityCritical attributes. And that function happens to call the run() function of the question. However, the finally part of the run() function is newer executed! Also, if you have a using(IDisposable object){ ... } and the SEHException occurs inside it; object's Dispose() function won't be called.
I've used the following function for calling the C++ function; and everything worked fine:
SafeCall(()=> call_external_cpp_function());
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
internal static void SafeCall(Action action)
{
try
{
action();
}
catch (System.Threading.ThreadAbortException) { throw; }
catch (System.Threading.ThreadInterruptedException) { throw; }
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

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.

Conditionally Use Lock in the Thread?

I have a method which is being used by multi-thread. In the method, there are some critical codes that I have to use lock to allow only ONE thread to access it. So, the code looks like:
private void RunCode()
{
...... // some other codes
lock (myLock)
{
...... // critical code01
}
...... // some other codes
lock (myLock)
{
...... // critical code02
}
....... // some other codes
}
This code is being used by multi-thread. Now, because of some workflow changes, we want to keep the code run as it is, BUT in some special cases, we want to run the critical codes immediately without the lock. We are ok even if the calculation result is not 100% correct because we do not lock it. So, the code should look like:
private void RunCode(bool isSpecial)
{
...... // some other codes
lock (myLock) // if isSpecial == true, do not lock it, otherwise, lock it
{
...... // critical code01
}
...... // some other codes
lock (myLock) // if isSpecial == true, do not lock it, otherwise, lock it
{
...... // critical code02
}
....... // some other codes
}
Based on research, it seems we have to do something like
if (isSpecial)
{
...... // critical code01
}
else
{
lock (myLock)
{
...... // critical code01
}
}
It will work, but the issue is that we have to repeat the critical code01 (and code02) twice. And these codes are pretty complex and closely related with other codes in the RunCode() method.
My question is: is there a better way to do this? Any suggestions? We are using c# .net, but any suggestions are welcome.
Thanks
Try use a Monitor class directly. It has a method TryEnter
Rewrite your code like this:
try
{
if (isSpecialCase || Monitor.TryEnter(myLock, TimeSpan.MaxValue))
{
// critical code01
}
}
finally
{
if (!isSpecialCase)
{
// lock was taken
Monitor.Exit(myLock);
}
}
What you want to do sounds pretty strange to say the least. But if I could not live without it, I would try defining a lambda expression on the fly and call that in these two locations. Something along the lines of
int aNumber = 5;
Action criticalCode01 = () => {Console.WriteLine("Foo! (repeat "+aNumber+" times)");};
if (isSpecial)
{
criticalCode01();
}
else
{
lock (myLock)
{
criticalCode01();
}
}
This is what you are looking for:
try
{
if (!isSpecialCase) Monitor.Enter(myLock);
// critical code01
}
finally
{
if (!isSpecialCase) Monitor.Exit(myLock);
}

Try in finally block

try
{
operation1();
operation2();
...
}
finally
{
try
{
finalizer_operation1();
finalizer_operation2();
}
finally
{
very_critical_finalizer_operation_which_should_occurs_at_the_end();
}
}
Is this ok? To have finalizer as another try/finally block (because finalizer_operationX() may throw and I must ensure that very_critical...() will happens at the end.
Quick googling for try in finally block brings nothing (will delete question if you give me a duplicate link), it should work, but I am unsure in design and possible problems with it.
I would not write the code this way. I don't like nesting try/catch/finally constructs. I prefer one per method.
My preference is to wrap each of those calls in its own method.
try
{
operation1();
operation2();
...
}
finally
{
cleanup();
}
public void cleanup() {
try
{
finalizer_operation1();
finalizer_operation2();
}
finally
{
very_critical_finalizer_operation_which_should_occurs_at_the_end();
}
}
Of course it is. A finally block will execute if control flow enters the corresponding try block.
The only exception is a call that shuts down the VM.

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