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 }
You should still investigate why the app pool has been stopped. Typically this means that the worker process has crashed a number of times in a short period of time. The Event Log, under the "System" category, should have info on when the faults were detected by the WAS service.
1 Answer. Show activity on this post. Stopping a site does not stop the application pool associated with the site. In fact the worker process serving the site still exists and the code loaded in the worker process still exists.
Cause: Application pools are configured to recycle when memory limits are exceeded. Resolution: Change the application pool recycling settings in Internet Information Services (IIS).
The error message "exceeded time limits during shut down" means the application failed to finish all current requests inside the process before application pool shutdown timeout reached. So either threads hang up or locked up. Besides, in some case, http.
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:
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."); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With