Home > General > .NET 4.0 and first chance exceptions

.NET 4.0 and first chance exceptions

.NET 4.0 introduced a new event that is raised for every exception that is thrown in an application domain. The FirstChanceException event is raised as soon as an exception is thrown. This includes any handled and unhandled exceptions.

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		Console.WriteLine("First chance exception: " + eventArgs.Exception.Message);
	};

	try 
	{
		Console.WriteLine("Before exception.");
		throw new Exception("Some error.");
	}
	catch
	{
		Console.WriteLine("Handled.");
	}
}

This code will produce the output:

Before exception.
First chance exception: Some error.
Handled.

However, if an exception is thrown within the event handler, the FirstChanceException event will be raised recursively. The code below will cause a stack overflow:

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		try
		{
			throw new Exception();
		}
		catch
		{
		}
	};

	try 
	{
		throw new Exception();
	}
	catch
	{
	}
}

This is important to remember if we use any third party libraries, such as a logging library like Log4Net, to log exceptions within the event handler. These third party libraries may throw an exception internally, which will cause the FirstChanceException event to be raised recursively. Even without the use of third party libraries, any code may unexpectedly thrown an exception, which will cause the event to be raised recursively and cause a stack overflow. The MSDN documentation mentions this fact:

You must handle all exceptions that occur in the event handler for the FirstChanceException event. Otherwise, FirstChanceException is raised recursively. This could result in a stack overflow and termination of the application. We recommend that you implement event handlers for this event as constrained execution regions (CERs), to keep infrastructure-related exceptions such as out-of-memory or stack overflow from affecting the virtual machine while the exception notification is being processed.

Unfortunately, the documentation doesn’t provide any code samples. I haven’t been able to figure a way to prevent stack overflows without resorting to a somewhat non-elegant solution. What we can do is check to see if the event handler is found multiple times in the current stack trace. If it is, we can immediately return to prevent the event from being raised again.

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		StackFrame[] frames = new StackTrace(1).GetFrames();
		MethodBase currentMethod = MethodBase.GetCurrentMethod();

		if (frames != null && frames.Any(x => x.GetMethod() == currentMethod))
			return;

		throw new Exception();
	};

	throw new Exception();
}

Instantiating StackTrace may throw an ArgumentOutOfRangeException if the parameter is negative, which is not what we’re doing here. The GetFrames() method may return null, so the if condition needs to check for null. The GetCurrentMethod() method may throw a TargetException if the method was invoked with a late-binding mechanism, which is not what we’re doing here.

The code above should be relatively safe and should prevent a stack overflow if an exception is thrown within the event handler.

  1. May 25, 2012 at 3:40 pm

    And posts like this is why I follow your blog and let it email me. This is the first time I’ve ever seen this, and that just shocks me! I can’t believe there was a whole brand new feature like this in .NET 4.0 that I was entirely unaware of.

    I can’t say I’d probably ever us this for the fact I probably don’t have any need to care about handled exceptions, and only care about unhandled, But it’s definitely interesting to know this exists.

  2. kiquenet
    March 2, 2016 at 9:35 am

    Great. Did you tried your code in production environment ?

    I would like use in ASP.NET 4.6.1 safely…

    public class Global : HttpApplication
    {

    protected void Application_Start(object sender, EventArgs e)
    {
    AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
    //AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
    }

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: