LegacyUnhandledExceptionPolicy doesn't allow to catch (and swallow) ThreadAbortException?
Asked Answered
F

1

5

I'm using .NET 1.1 compability mode for unhandled exception handling. The problem is that when LegacyUnhandledExceptionPolicy is set to "1" (which is what I want), I cannot catch and swallow ThreadAbortException.

Example code:

App.config:

<configuration>
   <runtime>
      <legacyUnhandledExceptionPolicy enabled="1"/>
   </runtime>
</configuration>

Code:

   class Program {

      static void Main(string[] args) {
         AppDomain.CurrentDomain.UnhandledException += _onBackgroundThreadCrash;
         var t = new Thread(_worker) { IsBackground = true };
         t.Start();
         Thread.Sleep(1000);
         t.Abort();
         Console.ReadLine();
      }

      private static void _worker() {
         try {
            while (true);
         } catch (ThreadAbortException) { 
            // expected thread exit, don't rethrow
         }
      }

      private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
         Console.WriteLine(e.ExceptionObject as Exception);
      }

   }

When legacy exceptions handling is "0" (OFF), the above code swallows ThreadAbortException queitly, as expected.

But, when legacy exceptions handling is "1" the above code prints ThreadAbortException to console, which is not what I expect.

Any ideas?

Thanks.

Fungicide answered 30/10, 2012 at 14:18 Comment(0)
P
7

You cannot catch a ThreadAbortException, it is always re-raised after catching it. There are two basic solutions to your problem.

First one is that you reset the abort request:

catch (ThreadAbortException) {
    // expected thread abort request, reset it and exit thread
    Thread.ResetAbort();
}

Second one is to address the other thing that happens when you enable legacy exception handling. The AppDomain.UnhandledException event is now also raised for non-fatal exceptions. Write your exception handler like this:

private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
    if (e.IsTerminating) {
        Console.WriteLine(e.ExceptionObject as Exception);
    }
}

I'd have to recommend the first solution, you really don't want unhandled exceptions that terminate a thread to leave no trace at all.

Parquet answered 30/10, 2012 at 16:15 Comment(2)
Thanks, all this makes sense. I still wonder why, when LegacyUnhandledExceptionPolicy=0 my handler is not called when there's ThreadAbortException?Fungicide
That's just part of the exception handling policy changes in .NET 2.0, AppDomain.UnhandledException is only raised for exceptions that terminate the app.Parquet

© 2022 - 2024 — McMap. All rights reserved.