Why does my IIS7 application pool shutdown after an exception in a DLL called from an ASP.NET page?

StackOverflow https://stackoverflow.com/questions/15975249

Question

I've read the posts ASP.NET application pool shutdown problem and IIS 7.5: problem with Application pool but they didn't answer my question.

I've got a C# ASP.NET page that in code-behind instantiates a class from a DLL supplied via the BIN directory, then calls a method on this instance. The method inside the DLL throws System.ArgumentException due to a non existing column in a DataRow object. The event log shows the following error:

Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace: 

The calling code in the ASP.NET page wraps the method call in a generic try-catch block. When I request the page, this crashes the corresponding application pool of my IIS instance and my web site is no longer available (Error 503). I manually have to restart the application pool and the site works again.

Update As requested the try catch block from the ASP.NET code behind:

try
{
    SomeExternalClass someExternalClass = new SomeExternalClass();
    someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
    // "smp" is an instance of "StatusMessagePanel", a control we use on all pages 
    // to show error information, basically a div container with an icon.
    smp.ShowError( ex.Message ); 
}

Now my question is why a relatively "simple" exception such as the System.ArgumentException being thrown when trying to access a non existing DataRow column, crashes the whole website? Neither does the generic try-catch block of the ASP.NET page help, nor should this be the reason to completely make the whole website unavailable, or is that a wrong assumption? I'd never have thought that this can basically take the (II)server down.

In anticipation of people telling me that I should check for column existence before I access them: I know about that and the legacy code has now been changed, but this isn't my question as described above, I'd like to know why the consequences are so drastic.

Update 2

The method in question being called inside the DLL starts a thread that is wrapped in a try-catch block:

[...]
try
{
    ThreadStart starter = () => CreateReport(...)
    Thread thread = new Thread( starter );
    thread.Start();
    if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
    {
        // Log some timeout warning
    }
    else
    {
        // Log information about successful report generation
    }
}
catch( Exception ex )
{
    // Log error information
}
Was it helpful?

Solution

Most likely your application pool is being shut down automatically by IIS's Rapid Fail Protection feature, as you note in the linked questions. If you check your event log, there may be multiple unhandled exceptions being thrown in rapid succession.

Simply put, enough unhandled exceptions in a configurable timespan (the default is 5 in 5 minutes) will shut down the AppPool, causing the 503 Service Unavailable response.

The reasoning behind this feature is that if you have a faulty application, you probably don't want it to be automatically restarted on every subsequent request, consuming resources and possibly corrupting data.

I have to admit that this isn't the "default" behavior I would have expected either.

Check out Rick Stahls explanation, it's a bit more in depth.

To really fix this, you need to catch the exception, or prevent the exception from being thrown (like @leppie suggests). Unhandled exceptions are supposed to tear down the entire executing process (meaning that single request/worker process, not IIS) - it makes .Net code much easier to debug, because it doesn't hide the errors or simply hang the application.

Note that this was changed in .Net 2.0:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

Update
Based on your update above, I don't think your exception is actually caught, if it is thrown from CreateReport(). That method is executing on a separate thread:

exception still thrown

You need a try-catch in the body of CreateReport() if there isn't one already:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}

OTHER TIPS

It happened to me once. The real error(in my case) was a stack-overflow that was shutting down the pool.

It seem like IIS was protecting itself from consuming too much resources.

I found the problem using DebugDiag.

Here is where I started: http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/

I'd like to understand why an exception in an external DLL can cause the IIS application pool to shutdown, even if the exception is being caught inside the DLL and also when calling the DLL's method from within the code behind of the ASP.NET page.

The external dll also run in your application pool. A major crash in this dll will also crash your application pool. Some exceptions can't be handle and the stackoverflow exception is one of them. Subject is discused here. Maybe it is what happen in your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top