Interlocked.Increment in finally block [duplicate] - c#

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.

Related

Can ThreadAbortException be raised in the middle of a Finally Block?

Asuming the following code is running in a seperate Thread:
try{
var stuffToDispose = new SomeClassThatNeedsDisposing();
//doing thing with stuffToDispose
}
finally{
if(stuffToDispose != null)
stuffToDispose.Dispose();
}
and this thread is aborted using the mechanic that raises the ThreadAbortException. Could the ThreadAbortException happen between the null-check and the Dispose()? Aka, in the middle of the finally block?
finally{
if(stuffToDispose != null)
//This is where the Exception would strike
stuffToDispose.Dispose();
}
I am pretty sure the answer is no, but someone else seems convinced it is possible.
In .NET Framework ThreadAbortException is handled in a special way both in catch and finally blocks:
If a ThreadAbortException is caught, it is automatically re-raised at the end of the catch block (unless it is suppressed by Thread.ResetAbort)
In a finally block the ThreadAbortException will not be 'activated' until the end of the whole block. This is an intended behavior. And that's why you can find sometimes obscure codes with and empty try {} block where everything is in the finally section. It guarantees that this section will not be aborted.
On the other hand, .NET Core does not support Thread.Abort (throws a PlatformNotSupportedException). The ThreadAbortException itself has not been removed (for compatibility reasons) so you can still throw it explicitly but I don't think it is still handled as described above (I did not test it).
Finally will not be interrupted if
Running this code under .NET 4.0.0-4.7.2 will lock infinitelly on Thread.Abort() printing foo and hanging in finally:
class Program
{
static void Main(string[] args)
{
var i = false;
var t = new Thread(() =>
{
try { Console.Write("foo"); } finally { while (true) { i=true; } }
});
t.Start();
Thread.Sleep(200);
t.Abort();
t.Join();
Console.WriteLine("bar = {0}", i);
Console.ReadKey();
}
}
Still, there is no guarantee that this will not execute sometimes in further versions.
Finally will be executed but interrupted if
Running same section under .NET 2.0-3.5 will print foobar = True, which implies it is interrupted.
But if you modify it like so:
var t = new Thread(() =>
{
try { Console.Write("foo"); } finally { while (true) { Console.Write(".");} }
});
It will run infinitelly like in first sample. This is ... strange.
Summary
Better to ask it dirrectly at Microsoft.
According to my tests, calling Thread.Abort does not interrupt a currently running finally block inside the thread.
Test code:
var thread = new Thread(() =>
{
try
{
}
catch (ThreadAbortException)
{
Console.WriteLine("ThreadAbortException");
throw;
}
finally
{
Console.WriteLine("Thread Finally Started");
Thread.Sleep(200);
Console.WriteLine("Thread Finally Finished");
}
})
{ IsBackground = true };
thread.Start();
Thread.Sleep(100);
Console.WriteLine("Aborting...");
thread.Abort();
thread.Join();
Output (.NET Framework 4.8):
Thread Finally Started
Aborting...
Thread Finally Finished
Keep in mind that Thread.Abort is not supported on .NET Core.
System.PlatformNotSupportedException: Thread abort is not supported on this platform.

Is it OK to have an empty while block when using WaitOne with named mutexes for IPC?

Basically, multiple instances of the same process will do this:
using (var mutex = new System.Threading.Mutex(false, MUTEX_NAME))
{
while (!mutex.WaitOne(100)) { /* wait to acquire mutex from other process */ }
try
{
doSynchronizedWork();
}
finally
{
mutex.ReleaseMutex();
}
}
Will there be any pitfalls? Can a process exit without releasing the mutex? Will an AbandonedMutexException actually be thrown if that happens? Or will another process just acquire the mutex? Something else?
Edit:
Looks like the correct way should be (at least my scenario) would be to do this:
using (var mutex = new System.Threading.Mutex(false, MUTEX_NAME))
{
bool lockObtained = false;
while (!lockObtained)
{
try
{
while (!mutex.WaitOne()) { /* wait to acquire mutex */ }
lockObtained = true;
}
catch (AbandonedMutexException ignored)
{
// mutex abandoned by another
// process before that process completed.
// We can now try to obtain it again.
}
}
try
{
doSynchronizedWork();
}
finally
{
mutex.ReleaseMutex();
}
}
What's the point of this? Simply wait without a timeout.
When a process exits all resources are cleaned up. An AbandonedMutexException must be assumed to be able to happen in IPC scenarios because the other process might fail at any time (due to a bug or out of memory and such).
In case you are doing this so that Thread.Abort works: Thread.Abort is super dangerous. Leave a comment and I'll be able to help you migrate to something better.

Exceptions inside the lock block

Say, if I have the following block on C# code:
public class SynchedClass
{
public void addData(object v)
{
lock(lockObject)
{
//Shall I worry about catching an exception here?
//Do the work
//arr.Add(v);
}
}
private List<object> arr = new List<object>();
private object lockObject = new object();
}
Shall I attempt to catch exceptions inside the lock block? (My main concern is that the exception may be raised inside the lock which will prevent the lock from being "unlocked".)
Lock will be released when exception escapes from the lock block.
That is because lock(){...} is translate by compiler roughly into:
Monitor.Enter(obj);
try{
// contents of the lock block
}finally{
Monitor.Exit(obj);
}
There is more to consider than just releasing the mutex.
An exception occuring within a lock will release the lock, but what state is the program in now? A thread waiting on the lock will now wake up, and will perhaps now be dealing with invalid state. This is a difficult problem with no ideal solution.
The best thing is to try to keep your locks as small as possible and to call methods that don't throw. (That's ignoring the elephant in the room that is the evil ThreadAbortException...)
For a good discussion of these issues, see Eric Lippert's article: Locks and exceptions do not mix.
A lock statement of the form "lock (x) ..." where x is an expression of a reference-type, is precisely equivalent to (C# 4.0):
bool entered = false;
try {
System.Threading.Monitor.Enter(x, ref entered);
...
}
finally { if (entered) System.Threading.Monitor.Exit(x); }

How best to dispose a thread that is sleeping because of AutoResetEvent.WaitOne()

I have a windows service that sends email in a one of 5 threads (done to increase the speed the service can send email):
private AutoResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (this.messageQueue.TryDequeue(out message))
{
this.block.Set();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
I have a Queue method that adds one or more new message to the messageQueue and calls block.Set() so that one of the 5 threads can send the message. When one of the threads is allowed to run, so long as there are messages in the queue, block.Set() is called so that the next message can be de-queued and another of 5 threads will work to send it. And so on, until the queue is empty. This all works OK.
However when I dispose my object, I set the disposing variable and then for each thread:
if(thread.ThreadState == ThreadState.Running)
{
thread.Join();
}
else if(thread.ThreadState == ThreadState.WaitSleepJoin)
{
thread.Abort();
}
Most of the time, the threads are sleeping due to the block.WaitOne and so the above code aborts the thread. However this causes thread abort exceptions to be logged. I could catch thread abort exceptions separately to other exceptions and choose not to log, but it doesn't seem very clean.
What is the best way to clean up these threads without causing this excess logging?
UPDATE:
I've changed the above to:
private ManualResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (!this.messageQueue.TryDequeue(out message) && !this.disposing)
{
// There's nothing else to send for now to block the sending threads
// unless we're disposing as we want the other threads to exit too
this.block.Reset();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
public void Dispose()
{
this.disposing = true;
this.block.Set();
foreach(Thread thread in this.sendingThreads) {
thread.Join();
}
this.block.Dispose();
this.sendingThreads = null;
}
Thanks for the help.
You are playing a very dangerous game. Your code is particularly prone to deadlock. You'll see the thread state as ThreadState.Running and the thread calls WaitOne() a microsecond later. Your Join() call will deadlock and never return.
You can get a thread that's blocked on a WaitOne() call to unblock by disposing the AutoResetEvent. That will throw a predicable exception, ObjectDisposedException, one you can catch. Use another ManualResetEvent to signal the thread to exit. No need for Thread.Abort() that way.
Use BlockingCollection instead. it will produce simple clean and short code which can be understood, managed and debugged...
one producer five consumers... threading 101.
http://msdn.microsoft.com/en-us/library/dd267312.aspx

Object synchronization method was called from an unsynchronized block of code. Exception on Mutex.Release()

I have found different articles about this exception but none of them was my case.
Here is the source code:
class Program
{
private static Mutex mutex;
private static bool mutexIsLocked = false;
static void Main(string[] args)
{
ICrmService crmService =
new ArmenianSoftware.Crm.Common.CrmServiceWrapper(GetCrmService("Armsoft", "crmserver"));
//Lock mutex for concurrent access to workflow
mutex = new Mutex(true, "ArmenianSoftware.Crm.Common.FilterCtiCallLogActivity");
mutexIsLocked = true;
//Create object for updating filtered cti call log
ArmenianSoftware.Crm.Common.FilterCtiCallLog filterCtiCallLog =
new ArmenianSoftware.Crm.Common.FilterCtiCallLog(crmService);
//Bind events
filterCtiCallLog.CtiCallsRetrieved += new EventHandler<ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs>(filterCtiCallLog_CtiCallsRetrieved);
//Execute filter
try
{
filterCtiCallLog.CreateFilteredCtiCallLogSync();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
}
static void filterCtiCallLog_CtiCallsRetrieved(object sender,
ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs e)
{
tryasasas
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
filterCtiCallLog.CreateFilteredCtiCallLogSync(); function executes requests to server, and raises some events, one of which is CtiCallsRetrieve event. And I need to release the mutex when this event is fired. But on calling the mutex.Release() function exception is thrown. CreateFilteredCtiCallLogSync works synchronously. What is the problem?
Keeping a bool around that indicates that the mutex is owned is a grave mistake. You are not making the bool thread-safe. You got into this pickle because you are using the wrong synchronization object. A mutex has thread-affinity, the owner of a mutex is a thread. The thread that acquired it must also be the one that calls ReleaseMutex(). Which is why your code bombs.
You in all likelihood need an event here, use AutoResetEvent. Create it in the main thread, call Set() in the worker, WaitOne() in the main thread to wait for the worker to complete its job. And dispose it afterwards. Also note that using a thread to perform a job and having your main thread wait for its completion is not productive. You might as well have the main thread do the job.
If you are actually doing this to protect access to an object that's not thread-safe (it isn't clear) then use the lock statement.
Another reason why this exception may occur:
if (Monitor.TryEnter(_lock))
{
try
{
... await MyMethodAsync(); ...
}
finally
{
Monitor.Exit(_lock);
}
}
I get this exception on Monitor.Exit when after 'await' another thread continues execution.
Edit:
Use SemaphoreSlim, because it doesn't require releasing thread to be the same.
You will also run into this exception if you do the following:
mutex.WaitOne();
… Some Work...
await someTask;
mutex.ReleaseMutex();
That's because the code after the await can be executed on a different thread from the line just before. Basically, it seems that if you asynch code now (in early 2020), Mutexes simply don't work. Use events or something.
I have found the problem. First several things about the filterCtiCallLog class. I have designed it so to work both asynchronous and synchronous. For first I have written code for asynchronous execution. I needed a way to trigger events from child worker thread to parent, to report the working state. For this I have used AsyncOperation class and it's post method. Here is the code part for triggering CtiCallsRetrieved event.
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog();
}
private void CreateFilteredCtiCallLog()
{
int count=0;
//do the job
//............
//...........
//Raise the event
createCallsAsync.Post(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count));
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
As you can see the code is executing synchronously. The problem here is in AsyncOperation.Post() method. I presumed that if it is called in the main thread it will act as simply triggering the event, not posting it to parent thread. However it wasn't the case. I don't know how it is working, but I have changed the code, to check if the CreateFilteredCtiCallLog is called sync or async. And if it is async call I used AsyncOperation.Post method, if not, I have simply triggered the EventHandler if it is not null. Here is the corrected code
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog(false);
}
private void CreateFilteredCtiCallLog(bool isAsync)
{
int count=0;
//do the job
//............
//...........
//Raise the event
RaiseEvent(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count),isAsync);
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void RaiseEvent(SendOrPostCallback callback, object state, bool isAsync)
{
if (isAsync)
createCallsAsync.Post(callback, state);
else
callback(state);
}
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
Thanks everybody for the answers!
I have seen this happen when you lock code using a Monitor, then call an async code and you get this, when using a lock(object) you get a compiler error, however between monitor.enter(object) and Monitor.Exist(object) the compiler does not complain... unfortunately.
Using a flag to attempt to monitor a kernel synchro object state will just not work - the point of using those synchro calls is that they work correctly without any explicit checking. Setting flags will just cause intermittent problems because the flag may be changed inappropriately due to interrupts between checking the flag and acting on it.
A mutex can only be released by the threat that acquired it. If you callback is called by a different thread, (one internal to CreateFilteredCtiCallLogSync() or a kernel thread pool), the release will fail.
It's not clear exactly what you are attempting to do. Presumably, you want to serialize access to CreateFilteredCtiCallLogSync() and the callback flags that the instance is available for re-use? If so, you could use a semaphore instead - init. it to one unit, wait for it at the start and release it in the callback.
Is there some issue where sometimes the callback is not called, and hence the try/finally/release? If so this way out seems a bit dodgy if the callback is asychronous and may be called by another thread after the setup thread has left the function.
I only had this one once or twice, and in every case it came about by trying to release a mutex I didn't own.
Are you sure the events are raised on the same thread the mutex was acquired on?
Although you mention that filterCtiCallLog.CreateFilteredCtiCallLogSync() is a blocking call, perhaps it spawns of worker threads that raise the event?
Maybe not the most meaningful error message, I've seen this happen in some third party code as below,
object obj = new object();
lock (obj)
{
//do something
Monitor.Exit(obj);//obj released
}//exception happens here, when trying to release obj
I have read the thread and got some ideas. But did not know what exactly need to do to solve the issue. I face the same error when uploading the image to the s3 at nopCommerce solution.And the below code is working for me.
using var mutex = new Mutex(false, thumbFileName);
mutex.WaitOne();
try
{
if (pictureBinary != null)
{
try
{
using var image = SKBitmap.Decode(pictureBinary);
var format = GetImageFormatByMimeType(picture.MimeType);
pictureBinary = ImageResize(image, format, targetSize);
}
catch
{
}
}
if (s3Enabled)
//await S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize);
// The above code was causing the issue. Because it is wait for the thread.
//So I replace the code below line and the error disappear. This also kind of same implementation by nopCommerce.
//The thread need to wait.
S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize).Wait();
else
File.WriteAllBytes(thumbFilePath, pictureBinary);
}
finally
{
mutex.ReleaseMutex();
}

Categories