CLR exits when a thread gets unhandled exception - c#

I have background threads in my application. When one of the threads gets an exception that is not handled the entire CLR exits.
Is it normal behavior, or is it a bug in the CLR?
I would expect that the thread will exit but the CLR will continue working.

The default behavior in .NET applications is to exit whenever an unhandled exception occurs. When an exception goes unhandled, the program is in an unknown and possibly unsteady state. Just because it happened in a background thread doesn't mean that the error won't affect the rest of the program. The most prudent course for the runtime in that situation is to dump the program.
You might look into AppDomain.CurrentDomain.UnhandledException, which will allow you to catch unhandled exceptions and react accordingly. A better solution is to wrap your thread proc with a try...catch. But only have it handle those exceptions it knows how to handle. Doing this:
void MyThreadProc()
{
try
{
// ...
}
catch
{
// handle all exceptions
// This is a BAD idea
}
}
Is a really bad idea, because it can mask exceptions that you really do want to be propagated to the main program.

Your expected behavior used to be the behavior back in 1.1. It was generally considered to have been a bad idea. When you have an unhandled exception in any thread, your process can be left in an inconsistent state. Updates to shared data may be partially applied, etc. The runtime doesn't have the information to safely handle this scenario, or even know how you want to handle this scenario, so its choice would amount to terminating the thread and leaving your program in a strange state. This could lead to resource leaks, hangs, corruption of data, etc. By terminating the process given an unhandled exception you know exactly what happens, the process ends.

This is a normal behavior of the CLR from v2.0. Here is a MSDN post on this. To avoid process from terminating you could use something like this
<legacyUnhandledExceptionPolicy enabled="1"/>
which is not advisable.

It is normal behavior. Perhaps you want to catch the exception to prevent the application from exiting.

Related

AppDomain.UnhandledException automatically re-throws handled exception

I'm trying to catch all unhandled exceptions in my app in order to conditionally handle those that can be without terminating the app, but I cannot solve a very basic problem: it doesn't stop the exception. An unhandled exception is thrown somewhere in the code, it comes here, the message box is shown, and then the application either shows that the same exceptions was unhandled (if in debug mode) or just crashes (if run without debugging). Meaning that the exception stays unhandled even though the handler was called.
App() {
AppDomain.CurrentDomain.UnhandledException += (s, a) => {
var ex = (Exception)a.ExceptionObject;
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
};
}
This is from a new, blank test project that has nothing in it but this code and a button that throws exception when clicked.
You are forgetting to terminate your program. So it continues on with the normal unhandled exception handling. Add this line:
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
The slightly laborious Marshal call ensures that another process that obtains the Process.ExitCode for your process gets a reasonable error indication. It is optional, merely recommended.
From MSDN:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.
In other words, it's just a handler to allow you to tell the user what happened, produce last minute save information if you need to be able to recover data, or do something like fire off a custom error report. It is not a catch block. To catch exceptions you have to use Try-Catch.
If this is really the behaviour that you want you could add the following to your application configuration file:
<legacyUnhandledExceptionPolicy enabled="1"/>
See Exceptions in Managed Threads.
It is not supposed to "stop" the exception, that behavior is by design:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.
Consider this the place were nobody else has bothered to handle the exception in question, there is nothing sensible left to do but log and die.
You should deal with those exceptions that should terminate the application closer to where they occur.
You aren't actually catching the unhandled exceptions but merely handling an event that occurs right before terminating the application (in release mode). Subscribing to this event doesn't count as catching an already unhandled exception.
From MSDN:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.

Abort current process from async task

I have some complex functions that run in an async Task spawned via the TPL, which could occasionally fail in unexpected ways. When such a failure occurs, this indicates a programming error which could have resulted in corrupted program state. Therefore, I don't want my program to catch the exception, handle it and "limp on", I want my process to crash and terminate.
I also want the thing to die in such a way that the Windows Error Reporting system detects it as a crash, and does all the useful debugging things like catching a minidump, sending it to Microsoft, etc.
I realise this may run counter to your opinions of what programs should do in error conditions, but the question is not about that.
The problem I have is, because the exception is raised from a task, it doesn't immediately cause the process to crash. It crashes some time later when the garbage collector, in its wisdom, decides to collect the "unobserved" exception.
I want the process to crash immediately, because...
The call stack and thread dump from the actual error is what I want to collect in the crash dump
The process "limping on" and crashing some indeterminate time later could cause further damage, as it will be working on a possibly corrupt program state
Users get confused about what operation actually caused the crash to occur
So, in short, the question is:
How can I cause my process to crash from an async Task, created with the TPL, such that Windows Error Reporting is able to create a useful minidump?
Thanks in advance!
You could try this, or something similar:
public static Task FailFastOnException(this Task task)
{
task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception),
TaskContinuationOptions.OnlyOnFaulted |
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.DetachedFromParent);
return task;
}
and then:
var t = Task.Factory.StartNew(…).FailFastOnException();
We've just used it a lot with "fire and forget" tasks that we want to take down the process if they for some reason fail.
Taken from a blog post written by Stephen Toub:
http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx
Take a look at ThrowUnobservedTaskExceptions (app.config setting):
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
If an exception that is associated with a Task has not been observed,
there is no Wait operation, the parent is not attached, and the
System.Threading.Tasks.Task.Exception property was not read the task
exception is considered to be unobserved.
In the .NET Framework 4, by
default, if a Task that has an unobserved exception is garbage
collected, the finalizer throws an exception and terminates the
process. The termination of the process is determined by the timing of
garbage collection and finalization.
To make it easier for developers
to write asynchronous code based on tasks, the .NET Framework 4.5
changes this default behavior for unobserved exceptions. Unobserved
exceptions still cause the UnobservedTaskException event to be raised,
but by default, the process does not terminate. Instead, the exception
is ignored after the event is raised, regardless of whether an event
handler observes the exception.
In the .NET Framework 4.5, you can use
the element in an application
configuration file to enable the .NET Framework 4 behavior of throwing
an exception.
You can also specify the exception behavior in one of
the following ways:
By setting the environment variable
COMPlus_ThrowUnobservedTaskExceptions (set
COMPlus_ThrowUnobservedTaskExceptions=1).
By setting the registry
DWORD value ThrowUnobservedTaskExceptions = 1 in the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework key.

Revisiting Thread.Abort() - is it safe?

MSDN on migrating legacy multithreaded applications (from this page on exception handling in threads):
In general, the change will expose previously unrecognized programming problems so that they can be fixed. In some cases, however, programmers might have taken advantage of the runtime backstop, for example to terminate threads. Depending on the situation, they should consider one of the following migration strategies:
Restructure the code so the thread exits gracefully when a signal is received.
Use the Thread.Abort method to abort the thread.
If a thread must to be stopped so that process termination can proceed, make the thread a background thread so that it is automatically terminated on process exit.
In all cases, the strategy should follow the design guidelines for exceptions. See Design Guidelines for Exceptions.
This suggests that using Thread.Abort is an appropriate way to terminate a thread. Has something changed while I wasn't looking? The last I'd heard was this could cause unexpected behaviours so shouldn't be used.
Thread.Abort is a lot safer than it used to be for the following reasons.
The runtime will defer aborts while execution is in unmanaged code.
The abort will allow finally blocks to execute.
However, there is still a problem with exactly when the ThreadAbortException gets injected. Consider this code.
public class Example
{
private DateTime value = DateTime.MinValue;
public void DoSomething()
{
try
{
value = DateTime.UtcNow;
}
finally
{
}
}
}
If this code were running on a 32-bit platform the value variable could be corrupted if Thread.Abort was called and the ThreadAbortException were injected in the middle of the write to value. Since DateTime is 8 bytes the write has to take place using more than one instruction.
It is possible to guard against this by placing critical code in a finally block and by using Constrained Execution Regions, but it would be incredibly difficult to get right for all but the simplest types your define. And even then you cannot just put everything in a finally block.
Generally speaking, Thread.Abort will kill threads, leaving the data they were processing at the time in an unknown state. The state being unknown, it's usually not safe to deal with that data anymore. However, when you're trying to terminate a process, you are not expecting to deal with that thread's data anymore, so why not abort it?
Well, the problem with Thread.Abort() is that will abort the thread possibly in the middle of work. That might cause your state to be corrupted. That's why is advisable to use a volatile bool flag to control the thread, and let the thread finish its task gracefully, but based on that flag.
For more details, I recall this blog post.

What is the recommended way to guard against resource leaks in the context of ThreadAbortException?

I'm working on improving the exception-safety of a piece of code and I realized that a raised ThreadAbortException may cause undesired resource leaks, even when guarding resources with the C# using construct. For instance, consider the following code (which could be running in a separate thread).
using (TextWriter writer = CreateWriter(filename))
{
// do something with the writer.
}
TextWriter CreateWriter(string filename)
{
return new CustomWriter(File.OpenWrite(filename));
}
If the thread running this code is abnormally terminated, then I would like the file handle referenced by filename to be closed immediately. Can I do this without replacing the use of the using construct with a try/finally block?
My assumption is that ThreadAbortException may be raised at anytime, which means I should pay attention to what is happening between statements. While I can guard against the exception in CreateWriter with a try/finally block, the using construct won't do the same until after the expression in the parenthesis is evaluated, meaning the file resource is left open if the exception occurs immediately after CreateWriter returns.
I understand that a finalizer will ultimately release the file handle, but I am wondering if there is a deterministic way to address this issue without catching ThreadAbortException in each place that CreateWriter is used.
Yes, the deterministic way of preventing this is by not using Thread.Abort. Ever. Signal to your threads that is is time to stop, and let them terminate gracefully. Thread.Abort is a great big red-herring, placed in the API solely to trip you up. ;)
http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
There is a tradeoff.
Be sure to close all resources immediately, even in the presence of ThreadAbortException
Have simpler code, but temporarily leak resources if Abort() is called
I assume that you are not calling Abort, and just want a way to be safe if someone else does. If you are calling Abort, then I'd advise that you don't. This isn't the only problem you will run into. There are other problems with Abort in the documentation.
#2 is a valid choice because callers of Abort() should expect this.
If you want to choose #1, then I don't think even a simple try/catch will help. If the ThreadAbortException can happen everywhere, then it can still happen after the file is opened (inside File.OpenWrite()) and before you can assign it to a variable that you can call Dispose() on -- you will have the same problem as using in your code.
You need semantics like
using (var handle = GetUnOpenedHandle()) {
handle.Open(); // this can't involve assignment to any field of handle
}
I'm not sure this is possible.
In many cases (but definitely not all) you could guard against a ThreadAbortException. Most of the critical code in the .NET BCL does this fairly well already. The problem is that it is really hard to get right. And for this reason most people recommend, and rightly so, to avoid aborting threads. Starting in version 2.0 the CLR made thread aborts a lot more tolerable and introduced a new set of APIs to help code authors guard against them. Take a look at Constrained Execution Regions for an in depth look at how all of this works.
I believe you are correct about your concerns with the example of the using block. For constrained execution regions to work correctly the out-of-band (asynchronous) exception must occur from within a try block. But, because of the way using expands out the expression is evaluated outside of the try block. Contrast that with the expansion of the lock block which evaluates the expression from within the try block. Well, that is true with version 4.0 of the framework anyway and that was changed specifically to guard against these exceptions.
So the question is why was the same change not made with the using block. According to Joe Duffy this was an acceptable omission because the assumption is that thread aborts should always be followed by a termination of the AppDomain which would fire off the finalizers anyway.
So yes. Your code is not tolerant of out-of-band (asynchronous) exceptions. But, the prevailing wisdom from those smarter than me is that it should not have to be.
A thread abort is most often used in the case of a fatal error, so your response should probably be to let your application terminate. If your trying to stop your own threads cleanly, use Thread.Join().

Finally: is it guaranteed to be invoked in any case

Is there any even small possibility that finally will not be invoked but application still be running?
I'm releasing semaphore there
finally
{
_semParallelUpdates.Release();
}
and afraid of lost of some of them.
Only critical finalizers have a strong guaranty to be called in case the shit hits the fan. You can inherit from CriticalFinalizerObject or SafeHandle to get this behavior. However, letting your finalizer do anything else than call code with a strong reliability contract is not advised. This code has to be able to run for instance, in situations where the system is out of memory.
Implementing a critical finalizer is only needed in situations where you want to be sure all unhandled resources are cleaned even if the app domain is unloaded (because for instance). Please note that you of course never have any guarantee that finalizers will run. In case of a power failure, you're out of luck. If you need more guarantees, you need some sort of transactional system (such as a database) that can get you this behavior.
If you are looking for ways to make your code reliable, I suggest reading the following article:
Reliability Best Practices
Another excellent article recommended by VinayC is the following:
Stephen Toub: Keep Your Code Running with the Reliability Features of the .NET Framework
Host windows operating system will terminate the program even in worst cases of uncaught fatal exceptions. But yes even in that case finally block will surely get executed.
In Framework 1.0 and 1.1, this was possible if a thread which is currently in the finally block was aborted using Thread.Abort. In current versions of the framework, I'm not aware of any such cases.
Is it guaranteed that your code will reach the finally? Yes (barring some cataclysmic event such as the world coming to an end... or, you know, your computer losing power or your OS crashing).
But it's important to recognize that, if it's absolutely critical that your code runs, you better make sure your code doesn't throw an exception itself!
Take this for example:
IDisposable someDisposableObject = null;
IDisposable someOtherDisposableObject = null;
try
{
someDisposableObject = GetDisposableObject();
throw new Exception("Holy crap, something bad happened.");
someOtherDisposableObject = GetOtherDisposableObject();
}
finally
{
// This will throw a NullReferenceException...
someOtherDisposableObject.Dispose();
// ...so this actually won't run.
someDisposableObject.Dispose();
}
So if you want your entire finally block to be run, it's important to write it properly so that an exception is (ideally) impossible.
The current thread will not leave the current stack frame unless or until the "finally" block executes or an exception is thrown from within the finally block itself. If a thread dies or gets blocked within a "try" block, execution will never leave the current stack frame, but it won't execute the finally "block" either.

Categories

Resources