Improved Unhandled Exception behavior in .NET 2.0

I recently posted a question about console apps and AppDomain.CurrentDomain.UnhandledException -- specifically, why doesn't it work as described in the MSDN documentation? I even filed an official bug report on this. I guess it worked, because Microsoft's Jonathan Keljo was kind enough to explain this behavior in the comments:

Sorry for the confusion. This behavior is actually the design, though the design can be a little convoluted at times.

The first thing to understand is that the UnhandledException event is not an unhandled exception "handler". Registering for the event, contrary to what the documentation says :-(, does not cause unhandled exceptions to be handled. (Since then they wouldn't be unhandled, but I'll stop with the circular reasoning already...) The UnhandledException event simply notifies you that an exception has gone unhandled, in case you want to try to save state before your thread or application dies. FWIW, I have filed a bug to get the docs fixed.

Just to complicate things, in v1.0 and 1.1, an unhandled exception did not always mean that your application would die. If the unhandled exception occurred on anything other than the main thread or a thread that began its life in unmanaged code, the CLR ate the exception and allowed your app to keep going. This was generally evil, because what would often happen was, for example, that ThreadPool threads would silently die off, one by one, until your application wasn't actually doing any work. Figuring out the cause of this kind of failure was nearly impossible. This may be why Jeff thought it worked before...he just always saw crashes on non-main threads.

In v2.0, an unhandled exception on any thread will take down the application. We've found that it's tremendously easier to debug crashes than it is to debug hangs or the silent-stoppage-of-work problem described above.

BTW, on my 1.1 machine the example from MSDN does have the expected output; it's just that the second line doesn't show up until after you've attached a debugger (or not). In v2 we've flipped things around so that the UnhandledException event fires before the debugger attaches, which seems to be what most people expect.

Jonathan Keljo
CLR Exceptions PM

It's good to hear that unhandled exception behavior will be more coherent in .NET 2.0. I can't think of any reason I would want the debugger to attach (or, if no debugger is registered, the .NET crash dialog to appear) before our global unhandled exception event fires!

I knew that exceptions were only handled on the main thread in .NET 1.1; you have to add the handler to any new managed thread you spawn. However, I've also seen the behavior Jonathan describes here:

if the unhandled exception [ occurs in ] a thread that began its life in unmanaged code, the CLR eats the exception and allows your app to keep going

I remember spending an entire day working on winforms drag and drop problems that were a side effect of this unwanted exception behavior-- in retrospect, I guess it's because drag and drop occurs on an unmanaged COM thread. Anyway, through a painful process of elimination, we finally decided that our code was encountering some kind of error and silently returning from functions. I'm looking forward to not going through that in .NET 2.0!

Read more

Stay Gold, America

We are at an unprecedented point in American history, and I'm concerned we may lose sight of the American Dream.

By Jeff Atwood · · Comments

The Great Filter Comes For Us All

With a 13 billion year head start on evolution, why haven't any other forms of life in the universe contacted us by now? (Arrival is a fantastic movie. Watch it, but don't stop there - read the Story of Your Life novella it was based on

By Jeff Atwood · · Comments

I Fight For The Users

If you haven't been able to keep up with my blistering pace of one blog post per year, I don't blame you. There's a lot going on right now. It's a busy time. But let's pause and take a moment

By Jeff Atwood · · Comments

The 2030 Self-Driving Car Bet

It's my honor to announce that John Carmack and I have initiated a friendly bet of $10,000* to the 501(c)(3) charity of the winner’s choice: By January 1st, 2030, completely autonomous self-driving cars meeting SAE J3016 level 5 will be commercially available for passenger

By Jeff Atwood · · Comments