Unobserved task exception handling with TopShelf - c#

I am using TopShelf framework which is just working great.
However I am having great trouble figuring out how to register a top level exception filter for unobserved task exceptions (i.e subscribing to TaskScheduler.UnobservedTaskException).
I tried different places to register to this event, but no matter what, I never get the notification when I throw exceptions from non awaited tasks.
How can I correctly get these notifications when using TopShelf.
Thanks.

My bad,
It had nothing related to TopShelf but to the behavior of TaskScheduler.UnobservedTaskException which must wait for the exception throwing task to be garbage collected before getting the exception :(

Related

How to crash on unhandled Task exception?

I'd like to properly understand the consequences of failing to observe an exception thrown on a Task used in a fire and forget manner without exception handling.
Here's an extract from CLR via C#, Third Edition by Jeffry Richter: "[...] when a Task object is garbage collected, its Finalize method checks to see if the Task experienced an unobserved exception; if it has, Task's Finalize method throws [an exception]. Since you cannot catch an exception thrown by the CLR's finalizer thread, your process is terminated immediately."
I am writing some test code to bring about a termination but am unable to cause one.
Using the test code here, I am able to see the TaskScheduler.UnobservedTaskException handler being called. However, if I comment out the event handler subscription, the exception appears to be swallowed and does not bring about termination of the program.
I've tried this using the .NET Framework on both versions 4 and 4.8 with a Release build.
How do I demonstrate that failing to observe an exception thrown on a Task does indeed cause a crash?
The problem is correctly identified by Jon Skeet in his comment to the original post.
The best resource I found concerning this topic is by Stephen Toub.
tldr:
"To make it easier for developers to write asynchronous code based on Tasks, .NET 4.5 changes the default exception behavior for unobserved exceptions. While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default. Rather, the exception will end up getting eaten after the event is raised, regardless of whether an event handler observes the exception. This behavior can be configured, though. A new CLR configuration flag may be used to revert back to the crashing behavior of .NET 4, e.g."
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled=”true”/>
</runtime>
</configuration>

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.

How does ASP.NET handle unhandled exceptions?

When writing for ASP.NET and, while the debugger is attached, if you visit a web page that throws an exception, the unhandled exception helper is launched at the line of code that caused the exception.
This occurs even if you only are catching unhandled exceptions and are not catching thrown exceptions. However, hitting F5, ignoring the exception, or not having the debugger attached does not cause the AppDomain to be torn down. Instead somehow ASP.NET handles the unhandled exception anyway.
How does this work, and can exception handling like this be implemented elsewhere so that other unhandled exceptions can be swallowed rather than kill the whole AppDomain or process?
Edit: To clarify, I understand how exception handling and try...catch blocks work. However, in this case it seems that the debugger is considering the exception unhandled while at the same time ASP.NET is wrapping the exception in a try...catch. That is the behavior I want to emulate.
How does this work,
asp.net just wraps executing code in whatever exception-handling code they want. asp.net webpage (or view, or controller) is just a class, and how to use it is entirely up to host (in our case, asp.net).
why does VS debugger break on it if it's handled?
There's a quote from MSDN documentation:
ASP.NET has a top-level exception handler that handles exceptions to show error pages to browser users. That top-level exception handler will stop an unhandled exception from breaking into the debugger unless Just My Code is turned on. Make sure that you enable Just My Code for ASP.NET debugging.
Which means that if you have "Just my code" enabled in VS Debug options (and it's enabled by default) you'll break at exceptions that are unhandled in your own code, irregardless of whether they are handled in your caller or not.
can exception handling like this be implemented elsewhere so that other unhandled exceptions can be swallowed rather than kill the whole AppDomain or process?
You can't do that, it is a security measure.
Your webpage is just a bunch of method calls from IIS & the ASP.NET Runtime, you're webpage isn't running alone in your appdomain. The code calling into your code has an ordinary try/catch block around that method call.
You could create a similar setup yourself:
For a ConsoleApplication, by placing a try/catch block around eveything in Main, meaning that you'l catch any exceptions that aren't handled elsewhere in your app.
For a Windows Forms application, by handling the Application.ThreadException event (Which allows you to hook into Windows Forms' message loop's try/catch block)
For a WPF appliaction, by handling the Application.DispatcherUnhandledException event (Which allows you to hook into WPF's message loop's try/catch block)
... or maybe you could use the AppDomain.UnhandledException event
The problem with these kinds of programs then would be: Where in the app should you continue?
The last question is solved easily in ASP.NET, since every page call is isolated from each other. The user just continues by navigating to a page again.

Should event handlers in C# ever raise exceptions?

As a general rule, are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to throw an exception (or allow to be thrown) that the class raising the event will have to handle?
Given that such an exception would stop other listeners to that event from being called subsequently, it seems a bit 'antisocial' to allow this to happen, but on the other hand, if there is an exception, what should it do?
Throwing an exception from a event handler is in many ways similar to throwing an exception from a IDisposable.Dispose method (or a C++ destructor). Doing so creates havoc for your caller because you leave them with little option.
Ignore the exception and let it propagate. This breaks their contract to inform all listeners of an event. This is a very real problem if anyone above them on the stack catches the exception.
Catch it call the other handlers and rethrow. But what happens if one of the others throw as well?
Swallow the exception. This is just bad in general. Event sources should have no knowledge of their caller and hence can't know what they're swallowing.
Crash the process because you're toast.
Of all of these #4 is the best option. But this is rarely done and can't be counted on.
I think in your component you really only have a few options
You are calling the code which is throwing and are in the best position to handle the exception. If it's not handleable by you then it's unreasonable to expect it to be handled by anyone else. Hence crash the process and be done with it.
Don't call the API which throws
The only two types of exceptions that should come out of events are serious, potentially process-ending ones like System.OutOfMemoryException or System.DllNotFoundException, and things that are clearly programming errors, like System.StackOverflowException or System.InvalidCastException. Catching and dropping these kinds of exceptions is never a good idea -- let them float up to the top and let the developer decide what to do with them on an application level.
As for the rest... any common or garden-variety exception like System.IO.IOException should be handled inside your event, and you should have some mechanism for returning such error conditions to the caller.
Some of the answers here suggest it's bad to throw from an event handler ("creates havoc for your caller", "tends to lead to very difficult to handle situations, and unexpected behavior",...).
IMHO this is nonsense.
In the general case, it's perfectly OK to throw from an event handler. Other event handlers won't run of course - neither will the event handler that throws run to the end, nor any other code between the firing of the event and the point where it's caught. So what? It's perfectly normal that code is not executed when an exception is thrown - if you need to guarantee it's executed, then use a finally block.
Of course in any specific case you may want to consider which, if any, exceptions it is appropriate to handle, just as you would with any other code.
As always, there are no hard and fast rules that apply in all circumstances. One of the answers here says "event handlers should be fast ... and close to error free...". A counterexample is the ASP.NET Page.Load event.
A general rule in .NET is that it's almost always a bad idea to swallow all exceptions: this applies to event handlers just as it does to any other code.
So the answer to the original question "are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to throw an exception" is very definitely yes.
Just as the answer to the question "are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to swallow exceptions" is also yes.
In an ideal world, event handlers shouldn't raise exceptions. Raising an exception in an event handler tends to lead to very difficult to handle situations, and unexpected behavior. As you mentioned- this blocks subsequent event handlers from seeing the event, and the exception propagates into the event producer's code since it raised the event.
Ideally, event handlers should be fast (if they're long running, they should try to schedule the work in a separate thread) and as close to error free as possible.
In an ideal word, exceptions should not exist. In a developer real word, exceptions are always expected and should be intercepted (caught), propagated or inhibited as situation asks.
So
are there ever any circumstances in
which it's acceptable for a method
responsible for listening to an event
to throw an exception
Yes. You can expect an exception from every method, responsible or not to an event.
To catch almost every exception from a Windows application use:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException

Unhandled Exception in Windows Service

I am using system.timer in a windows service application (c#) and have added:
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(MyExceptionHandler);
To handle my exceptions, does this work in a Windows Service as it does not seem to work?
Does anyone have any alternative ideas?
This mechanism will work to capture Unhandled Exceptions in any environment including Windows Services. However there are some limitations on what kind of exceptions can be handled in this way. For instance, a StackOverFlowException may be unhandled but do to it's nature you won't ever see it go through an UnhandledException handler.
Why do you think this is not working? Have you tried attaching to the process with a debugger , enabling first chance exceptions and see what is going on?
Why do you have an unhandled exception in a service? What is the exception? Some exceptions have "special behavior" (and another link here for .NET 4 changes to corrupted state exceptions).
Also, what are you trying to do in the handler? Maybe the actions you're trying to do in the handler are what's limited when running as a service.

Categories

Resources