Click here to monitor SSC

Simon Cooper

There's only one ThreadExceptionHandler

Published Thursday, October 07, 2010 11:10 AM

There can only ever be one Application.ThreadException handler. Yes, you read that correctly.

To give some context, the core of our error reporting code in SmartAssembly adds event handlers to AppDomain.CurrentDomain.UnhandledException (for general exceptions) and Application.ThreadException (for winforms exceptions) to display our error reporting dialog, or send the unhandled exception details back to the application developers as a bug report.

I was recently debugging an issue where any exceptions thrown after a call to Microsoft.Data.ConnectionUI.DataConnectionDialog.Show would not be picked up by our error reporting code. In other words, this:

throw new Exception();
DataConnectionDialog.Show(new DataConnectionDialog());
would display our error reporting dialog, and this:
DataConnectionDialog.Show(new DataConnectionDialog());
throw new Exception();
would display the standard .NET winforms error dialog. At some point during the call to Show, our exception handler was disappearing.

After quite a bit of digging, I noticed something odd about the definition of ThreadException:

public static event ThreadExceptionEventHandler ThreadException {
    add { 
        IntSecurity.AffectThreadBehavior.Demand(); 
 
        ThreadContext current = ThreadContext.FromCurrent();
        lock(current) { 
            current.threadExceptionHandler = value;
        }
    }
    remove { 
        ThreadContext current = ThreadContext.FromCurrent();
        lock(current) { 
            current.threadExceptionHandler -= value; 
        }
    } 
}

Did you spot it? The add method uses = rather than += to assign the new event handler, replacing any existing handlers! And indeed, the DataConnectionDialog.Show was adding & removing it's own exception handler during the method, deleting ours in the process. This bug is obviously a typo, as the remove method uses -=, as it should.

Microsoft has known about this since 2005, but (as of .NET 4) have yet to fix this typo. In the meantime, don't trust that any ThreadException handlers you add will still be there if an exception gets thrown!

Comments

 

qwertie said:

How can they not get around to fixing a typo this serious?! Well, I put in my vote on MS Connect.
April 12, 2011 4:37 AM
You need to sign in to comment on this blog

About Simon Cooper

Simon joined Red Gate as a software developer in 2007. He started off in the SQL Tools division, working on SQL Compare 7 and 8, moved onto Schema Compare for Oracle, and is now in the .NET division working on SmartAssembly.
Latest articles
A first look at SQL Server 2012 Availability Group Wait Statistics
 If you are trouble-shooting an AlwaysOn Availability Group topology, a study of the wait statistics... Read more...

SQL Server Prefetch and Query Performance
 Prefetching can make a surprising difference to SQL Server query execution times where there is a high... Read more...

SSIS Basics: Setting Up Your Initial Package
 When working with databases, the use of SQL Server Integration Services (SSIS) is a skill that often... Read more...

Checking Out SQL Backup Pro 7’s New Automatic Backup Verification
 Wouldn't it be great to offload the daily chore of checking the integrity of your production... Read more...

Chuck Lathrope: DBA of the Day
 Chuck Lathrope was a finalist for the Exceptional DBA of the Year award in 2009. We contacted him to... Read more...