Why is thread not interrupted when sleeping in finally block - c#

I have been looking all over MSDN and can't find a reason why Thread can not be interrupted when sleeping within finally block. I have tried aborting with no success.
Is there any way how to wake up thread when sleeping within finally block?
Thread t = new Thread(ProcessSomething) {IsBackground = false};
t.Start();
Thread.Sleep(500);
t.Interrupt();
t.Join();
private static void ProcessSomething()
{
try { Console.WriteLine("processing"); }
finally
{
try
{
Thread.Sleep(Timeout.Infinite);
}
catch (ThreadInterruptedException ex)
{
Console.WriteLine(ex.Message);
}
}
}
Surprisingly MSDN claims thread CAN be aborted in finally block: http://msdn.microsoft.com/en-us/library/aa332364(v=vs.71).aspx
"There is a chance the thread could abort while a finally block is running, in which case the finally block is aborted."
edit
I find Hans Passant comment as best answer since this explains why Thread sometimes can and can not be interrupted/aborted in finally block. And that is when process is shutting down.
thanks

Aborting and interrupting threads should be avoided if possible as this can corrupt the state of a running program. For example, imagine you aborted a thread that was holding locks open to resources, these locks would never be released.
Instead consider using a signalling mechanism so that threads can co-operate with each other and so handle blocking and unblocking gracefully, e.g:
private readonly AutoResetEvent ProcessEvent = new AutoResetEvent(false);
private readonly AutoResetEvent WakeEvent = new AutoResetEvent(false);
public void Do()
{
Thread th1 = new Thread(ProcessSomething);
th1.IsBackground = false;
th1.Start();
ProcessEvent.WaitOne();
Console.WriteLine("Processing started...");
Thread th2 = new Thread(() => WakeEvent.Set());
th2.Start();
th1.Join();
Console.WriteLine("Joined");
}
private void ProcessSomething()
{
try
{
Console.WriteLine("Processing...");
ProcessEvent.Set();
}
finally
{
WakeEvent.WaitOne();
Console.WriteLine("Woken up...");
}
}
Update
Quite an interesting low-level issue. Although Abort() is documented, Interrupt() is much less so.
The short answer to your question is no, you cannot wake a thread in a finally block by calling Abort or Interrupt on it.
Not being able to abort or interrupt threads in finally blocks is by design, simply so that finally blocks have a chance to run as you would expect. If you could abort and interrupt threads in finally blocks this could have unintended consequences for cleanup routines, and so leave the application in a corrupted state - not good.
A slight nuance with thread interrupting, is that an interrupt may have been issued against the thread any time before it entered the finally block, but whilst it was not in a SleepWaitJoin state (i.e. not blocked). In this instance if there was a blocking call in the finally block it would immediately throw a ThreadInterruptedException and crash out of the finally block. Finally block protection prevents this.
As well as protection in finally blocks, this extends to try blocks and also CERs (Constrained Execution Region) which can be configured in user code to prevent a range of exceptions being thrown until after a region is executed - very useful for critical blocks of code which must be completed and delay aborts.
The exception (no pun intended) to this are what are called Rude Aborts. These are ThreadAbortExceptions raised by the CLR hosting environment itself. These can cause finally and catch blocks to be exited, but not CERs. For example, the CLR may raise Rude Aborts in response to threads which it has judged to be taking too long to do their work\exit e.g. when trying to unload an AppDomain or executing code within the SQL Server CLR. In your particular example, when your application shuts down and the AppDomain unloads, the CLR would issue a Rude Abort on the sleeping thread as there would be an AppDomain unload timeout.
Aborting and interrupting in finally blocks is not going to happen in user code, but there is slightly different behavior between the two cases.
Abort
When calling Abort on a thread in a finally block, the calling thread is blocked. This is documented:
The thread that calls Abort might block if the thread that is being aborted is in a protected region of code, such as a catch block, finally block, or constrained execution region.
In the abort case if the sleep was not infinite:
The calling thread will issue an Abort but block here until the finally block is exited i.e. it stops here and does not immediately proceed to the Join statement.
The callee thread has its state set to AbortRequested.
The callee continues sleeping.
When the callee wakes up, as it has a state of AbortRequested it will continue executing the finally block code and then "evaporate" i.e. exit.
When the aborted thread leaves the finally block: no exception is raised, no code after the finally block is executed, and the thread's state is Aborted.
The calling thread is unblocked, continues to the Join statement and immediately passes as the called thread has exited.
So given your example with an infinite sleep, the calling thread will block forever at step 1.
Interrupt
In the interrupt case if the sleep was not infinite:
Not so well documented...
The calling thread will issue an Interrupt and continue executing.
The calling thread will block on the Join statement.
The callee thread has its state set to raise an exception on the next blocking call, but crucially as it is in a finally block it is not unblocked i.e. woken.
The callee continues sleeping.
When the callee wakes up, it will continue executing the finally block.
When the interrupted thread leaves the finally block it will throw a ThreadInterruptedException on its next blocking call (see code example below).
The calling thread "joins" and continues as the called thread has exited, however, the unhandled ThreadInterruptedException in step 6 has now flattened the process...
So again given your example with an infinite sleep, the calling thread will block forever, but at step 2.
Summary
So although Abort and Interrupt have slightly different behavior, they will both result in the called thread sleeping forever, and the calling thread blocking forever (in your example).
Only a Rude Abort can force a blocked thread to exit a finally block, and these can only be raised by the CLR itself (you cannot even use reflection to diddle ThreadAbortException.ExceptionState as it makes an internal CLR call to get the AbortReason - no opportunity to be easily evil there...).
The CLR prevents user code from causing finally blocks to be prematurely exited for our own good - it helps to prevent corrupted state.
For an example of the slightly different behavior with Interrupt:
internal class ThreadInterruptFinally
{
public static void Do()
{
Thread t = new Thread(ProcessSomething) { IsBackground = false };
t.Start();
Thread.Sleep(500);
t.Interrupt();
t.Join();
}
private static void ProcessSomething()
{
try
{
Console.WriteLine("processing");
}
finally
{
Thread.Sleep(2 * 1000);
}
Console.WriteLine("Exited finally...");
Thread.Sleep(0); //<-- ThreadInterruptedException
}
}

The whole point of a finally block is to hold something that will not be affected by an interrupt or abort and will run to normal completion no matter what. Permitting a finally block to be aborted or interrupted would pretty much defeat the point. Sadly, as you noted, finally blocks can be aborted or interrupted due to various race conditions. This is why you will see many people advising you not to interrupt or abort threads.
Instead, use cooperative design. If a thread is supposed to be interrupted, instead of calling Sleep, use a timed wait. Instead of calling Interrupt signal the thing the thread waits for.

Related

killing a long running thread that is blocking on another child process to end

So, a little background. I have a program that creates a child process that runs long term and does some processing that we don't really care about for this question. It exists, and it needs to keep existing. So after starting that child process I start a thread that watches that child process and blocks waiting for it to end by Process.WaitForExit() and if it ends, it will restart the child process and then wait again. Now the problem is, how do I gracefully shut all of this down? If I kill the child process first, the thread waiting on it will spin it up again, so I know that the watcher thread needs to be killed first. I have been doing this by Thread.Abort() and then just catching the ThreadAbortException and returning ending the watcher thread and then I kill my child process. But I have been told that Thread.Abort() should be avoided at all costs and is possibly no longer supported in .Net core? So my question is why is Thread.Abort() so dangerous if I am catching the ThreadAbortException? and what is the best practice for immediately killing that thread so it doesn't have a chance to spin up the child thread again during shut down?
What you are looking for is way to communicate across threads. There are multiple ways to do this but they all have specific conditions applicable.
For example mutex and semaphore are available across processes. events or wait handles are specific to a given process, etc. Once you know the details of these you can use them to send signal from one thread to another.
A simple setup for your requirement can be -
Create a resetevent before spawning any of your threads.
Let the child thread begin. In your parent wait on the reset event that you have created.
Let the child thread reset the event.
In your parent thread the wait state is completed, you can take further actions, such as kicking of the thread again and waiting on it or simply cleaning up and walking out of execution.
Thread.Abort is an unclean way of finishing your processing. If you read the msdn article here - https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-6.0 the remark clearly tells you that you cant be sure what current state your thread execution was in. Your thread may not get opportunity to follow up with important clean up tasks, such as releasing resources that it does not require no more.
This can also lead to deadlock if you have more complicated constructs in place, such as thread being aborted doing so from protected region of code, such as a catch block or a finally block. If the thread that calls Abort holds a lock that the aborted thread is waiting on, a deadlock can acquire.
Key to remember in multithreading is that it is your responsibility to let the logic have a clean way of reaching to completion and finish thread's execution.
Please note that steps suggested above is one way of doing it. Depending on your requirements it can be restructured/imporved further. For example, if you are spawning another process, you will require kernel level objects such as mutex or semaphore. Objects like event or flag cant work across the process.
Read here - https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives for more information.
As mentioned by others, Thread.Abort has major issues, and should be avoided if at all possible. It can raise the exception at any point in the code, in a possibly completely unexpected location, and possibly leave data in a highly corrupted state.
In this instance, it's entirely unnecessary.
You should change the waiting thread to use async instead. For example, you can do something like this.
static async Task RunProcessWithRestart()
{
using cancel = new CancellationTokenSource();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
static CancellationTokenSource cancel;
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}
public static void ShutdownWaitForProcess()
{
cancel.Cancel();
}
An alternative, which doesn't require calling Cancel() from a separate shutdown function, is to subscribe to the AppDomain.ProcessExit event.
static async Task RunProcessWithRestart()
{
using var cancel = new CancellationTokenSource();
AppDomain.ProcessExit += (s, e) => cancel.Cancel();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}

check if thread finished its method before "killing" it c#

I have 2 threads in my program. 1 is handling a GUI and the other is doing some word automation. Lets call them GUIThread and WorkerThread.
The WorkerThread is looping through methods using recursion.
The WorkerThread is only alive while doing the word automation and the user must be able to stop the word automation. Therefore I have implemented a "Stop" button on the GUI which simply kills/terminates the WorkerThread. However if I kill the WorkerThread while it's in the middle of a method it sometimes causes a problem in my word document (this is a longer story) and that's why I want to check if the WorkerThread has finished/returned from a method before I kill it.
This is what my code does when I hit the "Stop" button:
//Stops the worker thread = stops word automation in process
workerThread.Abort();
//This blocks the thread until the workerThread has aborted
while (workerThread.IsAlive) ;
My own suggestion/workaround for the problem was to have a global variable I could set each time the WorkerThread entered and left a method but this doesn't seem right to me. I mean I think there must be an easier way to deal with it.
However if I kill the WorkerThread while it's in the middle of a method it sometimes causes a problem in my word document
This is why you should never kill a thread. You can't say what the thread was doing, whether it is safe to kill? etc etc.
Abort isn't doing what you expect it to do. Look at the documentation, it is subtle Calling this method usually terminates the thread. Note the word usually and not always.
Yes, Abort will not kill the thread always. For example if the thread was running unmanaged code, CLR will not abort the thread, instead it will wait for the thread to return to managed code.
Sameway Abort will not do its job when thread is in Constrained Execution Region, finally blocks etc.
The CLR delays thread aborts for code that is executing in a CER.
For example: Try to run the following code and see what happens.
private void IWillNeverReturn()
{
Thread thread = new Thread(() =>
{
try
{
}
finally
{
while (true)
{ }
}
});
thread.Start();
Thread.Sleep(1000);
thread.Abort();
}
Let the thread decide when it should complete, Tell the thread that it should stop as soon as it can. You tell it using CancellationToken.
If you google for Thread.Abort Evil, you'll find lot of useful resources, Here is one.

CLR via C# 4th Ed. - Confused about waiting for Task deadlock

Jeffrey Richter pointed out in his book 'CLR via C#' the example of a possible deadlock I don't understand (page 702, bordered paragraph).
The example is a thread that runs Task and call Wait() for this Task. If the Task is not started it should possible that the Wait() call is not blocking, instead it's running the not started Task. If a lock is entered before the Wait() call and the Task also try to enter this lock can result in a deadlock.
But the locks are entered in the same thread, should this end up in a deadlock scenario?
The following code produce the expected output.
class Program
{
static object lockObj = new object();
static void Main(string[] args)
{
Task.Run(() =>
{
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() =>
{
lock (lockObj)
{
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
}
});
taskToRun.Start();
lock (lockObj)
{
taskToRun.Wait();
}
}).Wait() ;
}
}
/* Console output
Program starts running on thread 3
0 from Thread 3
1 from Thread 3
2 from Thread 3
3 from Thread 3
4 from Thread 3
5 from Thread 3
6 from Thread 3
7 from Thread 3
8 from Thread 3
9 from Thread 3
*/
No deadlock occured.
J. Richter wrote in his book "CLR via C#" 4th Edition on page 702:
When a thread calls the Wait method, the system checks if the Task that the thread is waiting for has started executing. If it has, then the thread calling Wait will block until the Task has completed running. But if the Task has not started executing yet, then the system may (depending on the TaskScheduler) execute the Trask by using the thread that called Wait. If this happens, then the thread calling Wait does not block; it executes the Task and returns immediatlely. This is good in that no thread has blocked, thereby reducing resource usage (by not creating a thread to replace the blocked thread) while improving performance (no time is spet to create a thread an there is no contexte switcing). But it can also be bad if, for example, thre thread has taken a thread synchronization lock before calling Wait and thren the Task tries to take the same lock, resulting in a deadlocked thread!
If I'm understand the paragraph correctly, the code above has to end in a deadlock!?
You're taking my usage of the word "lock" too literally. The C# "lock" statement (which my book discourages the use of), internally leverages Monitor.Enter/Exit. The Monitor lock is a lock that supports thread ownership & recursion. Therefore, a single thread can acquire this kind of lock multiple times successfully. But, if you use a different kind of lock, like a Semaphore(Slim), an AutoResetEvent(Slim) or a ReaderWriterLockSlim (without recursion), then when a single thread tries to acquire any of these locks multiple times, deadlock occurs.
In this example, you're dealing with task inlining, a not-so-rare behavior of the TPL's default task scheduler. It results in the task being executed on the same thread which is already waiting for it with Task.Wait(), rather than on a random pool thread. In which case, there is no deadlock.
Change your code like below and you'll have a dealock:
taskToRun.Start();
lock (lockObj)
{
//taskToRun.Wait();
((IAsyncResult)taskToRun).AsyncWaitHandle.WaitOne();
}
The task inlining is nondeterministic, it may or may not happen. You should make no assumptions. Check Task.Wait and “Inlining” by Stephen Toub for more details.
Updated, the lock does not affect the task inlining here. Your code still runs without deadlock if you move taskToRun.Start() inside the lock:
lock (lockObj)
{
taskToRun.Start();
taskToRun.Wait();
}
What does cause the inlining here is the circumstance that the main thread is calling taskToRun.Wait() right after taskToRun.Start(). Here's what happens behind the scene:
taskToRun.Start() queues the task for execution by the task scheduler, but it hasn't been allocated a pool thread yet.
On the same thread, the TPL code inside taskToRun.Wait() checks if the task has already been allocated a pool thread (it hasn't) and executes it inline on the main thread. In which case, it's OK to acquired the same lock twice without a deadlock.
There is also a TPL Task Scheduler thread. If this thread gets a chance to execute before taskToRun.Wait() is called on the main thread, inlining doesn't happen and you get a deadlock. Adding Thread.Sleep(100) before Task.Wait() would be modelling this scenario. Inlining also doesn't happen if you don't use Task.Wait() and rather use something like AsyncWaitHandle.WaitOne() above.
As to the quote you've added to your question, it depends on how you read it. One thing is for sure: the same lock from the main thread can be entered inside the task, when the task gets inlined, without a deadlock. You just cannot make any assumptions that it will get inlined.
In your example, no deadlock occurs because the thread scheduling the task and the thread executing the task happen to be the same. If you were to modify the code such that your task ran on a different thread, you would see the deadlock occur, because two threads would then be contending for a lock on the same object.
Your example, modified to create a deadlock:
class Program {
static object lockObj = new object();
static void Main(string[] args) {
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() => {
lock (lockObj) {
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
}
});
lock (lockObj) {
taskToRun.Start();
taskToRun.Wait();
}
}
}
This example code has two standard threading problems. To understand it, you first have to understand thread races. When you start a thread, you can never assume it will start running right away. Nor can you assume that the code inside the thread arrives at a particular statement at a particular moment in time.
What matters a great deal here is whether or not the task arrives at the lock statement before the main thread does. In other words, whether it races ahead of the code in the main thread. Do model this as a horse race, the thread that acquired the lock is the horse that wins.
If it is the task that wins, pretty common on modern machines with multiple processor cores or a simple program that doesn't have any other threads active (and probably when you test the code) then nothing goes wrong. It acquires the lock and prevents the main thread from doing the same when it, later, arrives at the lock statement. So you'll see the console output, the task finishes, the main thread now acquires the lock and the Wait() call quickly completes.
But if the thread pool is already busy with other threads, or the machine is busy executing threads in other programs, or you are unlucky and you get an email just as the task starts running, then the code in the task doesn't start running right away and it is the main thread that acquired the lock first. The task can now no longer enter the lock statement so it cannot complete. And the main thread can not complete, Wait() will never return. A deadly embrace called deadlock.
Deadlock is relatively easy to debug, you've got all the time in the world to attach a debugger and look at the active threads to see why they are blocked. Threading race bugs are incredibly difficult to debug, they happen too infrequently and it can be very difficult to reason through the ordering problem that causes them. A common approach to diagnose thread races is to add tracing to the program so you can see the order. Which changes the timing and can make the bug disappear. Lots of programs were shipped with the tracing left on because they couldn't diagnose the problem :)
Thanks #jeffrey-richter for pointing it out, #embee there are scenario when we use locks other than Monitor than a single thread tries to acquire any of these locks multiple times, deadlock occurs. Check out the example below
The following code produce the expected deadlock. It need not be nested task the deadlock can occur without nesting also
class Program
{
static AutoResetEvent signalEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Task.Run(() =>
{
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() =>
{
signalEvent.WaitOne();
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
});
taskToRun.Start();
signalEvent.Set();
taskToRun.Wait();
}).Wait() ;
}
}

exception handling on background threads using Thread pool

The application I am working on uses thread pool. Here's the basic pseudo code.
On the main thread
foreach(Object obj in Component.GetObject())
{
//Invoke the thread pool providing the call back (method to be called on the background// thread) and pass the object as the parameter.
}
//Wait for the threads to complete.
The "Component.GetObject" will basically return a CLR object using Yield return. This object needs to be processed by two other components on threads. So we are invoking the thread pool providing the call back method (that will invoke the two components).
If there is an exception on the spawned thread/s, the parent thread needs to be notified so that it can break out of the for loop (i.e. stop spawing more threads), wait for the spawned threads to complete and then handle the exception.
Based on my reading, one of the approaches would be have a "flag" variable on the main thread. If there is an exception on the spawned thread, the thread would set the variable using locking mechanism. The parent thread would check the "flag" variable before spawning new threads.
I would like to know if there is a better approach for handling this scenario. Thread pool is being used since it manages the queueing of threads if the "for" loop spawns more threads than the thread pool limit.
I think the standard way is to just throw the exception and let the code that handles the thread pool handle it. Is this not possible in your implementation?
Even if the exception is handled, nothing is stopping you from throwing one into your main thread from one of the other threads.
//thread code
try{
//something
}
catch (IOException e){
//handle your exception
//and then throw another one, that you can catch later
throw new ThreadFailedException()
}

C# Thread Termination and Thread.Abort()

In MSDN, the description of the Thread.Abort() method says: "Calling this method usually terminates the thread."
Why not ALWAYS?
In which cases it doesn't terminate the thread?
Are there any other possibility to terminate threads?
Thread.Abort() injects a ThreadAbortException on the thread. The thread may cancel the request by calling Thread.ResetAbort(). Also, there are certain code parts, such as finally block that will execute before the exception is handled. If for some reason the thread is stuck in such a block the exception will never be raised on the thread.
As the caller has very little control over the state of the thread when calling Abort(), it is generally not advisable to do so. Pass a message to the thread requesting termination instead.
In which cases it doesn't terminate the thread?
This question is a duplicate.
What's wrong with using Thread.Abort()
Are there any other posibility to terminate threads?
Yes. Your problem is that you should never start up a thread that you cannot tell politely to stop, and it stops in a timely manner. If you are in a situation where you have to start up a thread that might be (1) hard to stop, (2) buggy, or worst of all (3) hostile to the user, then the right thing to do is to make a new process, start the thread in the new process, and then terminate the process when you want the thread to go down. The only thing that can guarantee safe termination of an uncooperative thread is the operating system taking down its entire process.
See my excessively long answer to this question for more details:
Using lock statement within a loop in C#
The relevant bit is the bit at the end where I discuss what the considerations are regarding how long you should wait for a thread to kill itself before you abort it.
Why not ALWAYS?
In which cases it doesn't termenate the thread?
For starters, a thread may catch a ThreadAbortException and cancel its own termination. Or it could perform a computation that takes forever while you're trying to abort it. Because of this, the runtime can't guarantee that the thread will always terminate after you ask it to.
ThreadAbortException has more:
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Since the thread can do an unbounded computation in the finally blocks, or call Thread.ResetAbort() to cancel the abort, there is no guarantee that the thread will ever end.
You don't need to Abort() a thread manually. The CLR will do all of the dirty work for you if you simply let the method in the thread return; that will end the thread normally.
FileStream.Read() to a named pipe that is currently not receiving anything (read call blocks while waiting for incoming data) will not respond to Thread.Abort(). It remains inside the Read() call.
What if a thread is holding a lock and is aborted / killed ? Resources remain stuck
It works fine when when a thread calls
abort itself but not by other thread.
Abort, forcefully terminates the
affected thread even if it has not
completed its task and provides no
opportunity for the cleanup of
resources
reference MSDN
see: Managed Threading Best Practices
I can't seem to abort a thread that is stuck in a loop:
//immortal
Thread th1 = new Thread(() => { while (true) {}});
I can however abort the thread if sleeps during the loop:
//mortal
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }});
ThreadAborts will not occur inside a finally block or between BeginCriticalRegion and EndCriticalRegion
Because you can catch the ThreadAbortException and call Thread.ResetAbort inside the handler.
OT: For a comprehensive, language-agnostic, questionably useful and darned funny take on concurrency, see Verity Stob!
As john feminella stated from MSDN
When this exception is raised, the runtime executes all the finally
blocks before ending the thread.
For example this Abort never ends:
var thread = new Thread(action) { IsBackground = true };
thread.Start();
Thread.Sleep(2000);
thread.Abort();
while (!thread.Join(1000))
{
Console.WriteLine(thread.ThreadState);
}
void action()
{
try
{
while (true) { }
}
catch { }
finally
{
while (true) { }
}
}
I've had cases where the thread has been too busy to hear the Abort() call, which usually results in a ThreadAbortingException being thrown to my code.

Categories