Friday, June 10, 2005

Back last year, I outlined a problem I had with calling Response.End from a thread other than the thread that handled the request.  It stemmed from a progress mechanism we had implemented that had the ability to cancel long-running tasks when the user hit stop or closed the browser.  As it turns out, that wasn't the whole story.

We recently added a few reports where, the majority of the time, gathering the data takes over a couple of minutes.  While doing memory and performance optimizations, we noticed our worker process was recycling with the following message in the System event log:

A process serving application pool 'XXXXXXXXXX' terminated unexpectedly. The process id was '####'. The process exit code was '0xff'.

Googling for this error doesn't do you much good since it could be caused by a variety of reasons.  Most of the advice I came across wasn't well thought out and made quite a few bad assumptions.  So we added some more debug logging and determined that this was happening when our canceling mechanism kicked in when a user decided they didn't really want to wait 5 minutes for the report.  I was greatly puzzled by this since this feature had been tested thoroughly and had been running in production for some time.  Looking back through the server logs, it was evident that it had been happening all along, just not very often. We had just gotten the performance on the vast majority of pages to be very good and it wasn't an issue.  The problem only came to the surface when we added the report that always takes a while.

Here's the problem.  If the handling thread is aborted, it causes a condition that IIS considers to be bad and that forces the worker process to recycle. (presumably, there is some communication that doesn't occur) This doesn't happen when Response.End() is called because it passes a special exception as the exception state to Thread.Abort.  The HttpApplication catches ThreadAbortException and checks the ExceptionState.  If it is an HttpApplication.CancelModuleException, it knows there was either a timeout, or Response.End() was called, and it cancels the Thread.Abort by calling ResetAbort which allows the thread to continue running at that point.  I thought that was pretty slick.

When I was aborting the handling thread, I was on a different thread, so I had to call Thread.Abort manually, so CancelModuleException was not being used, so the thread was ending completely and causing the recycle.  Since HttpApplication.CancelModuleException is internal (and rightly so) I could not simply use that mechanism.

The good news is that the Unload event always happens (for all practical purposes), even when the thread is being aborted.  So I added my own PageIsCancelling property to our base class Page and check it, along with the current ThreadState in Unload, and cancel any pending abort if the page is canceling.  So, the abort is contained within the callstack of the page, and the thread stays alive and all is well.  No more crazy recycling.

As an aside, it seems this is aggravated by multiple processors, which might explain how it passed testing on the dev's machine.  Although I don't have any proof of this.

posted on Friday, June 10, 2005 10:50:44 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
Related posts:
LinqToStdf now on CodePlex
Image Slicer for Deep Zoom in Silverlight 2
Silverlight limitations and Constrained Callvirt in IL
What are the generic Delegates in the framework for?
What is System.__Canon and why is it on my stack?
Adding support for .ashx-based views in ASP.net MVC
Tracked by:
"home sales in orlando" (home sales in orlando) [Trackback]
"hauling big game out" (hauling big game out) [Trackback]
"jewish webcasting" (jewish webcasting) [Trackback]
"xm radio" (xm radio) [Trackback]
"king size bedding" (king size bedding) [Trackback]
"VITAMIN C" (VITAMIN C) [Trackback]
"definicion de xenical" (definicion de xenical) [Trackback]
"olympic limosine" (olympic limosine) [Trackback]
"the matchmaker synopsis" (the matchmaker synopsis) [Trackback]
"shootout at the ok corral" (shootout at the ok corral) [Trackback]
"sms transcom" (sms transcom) [Trackback]
"summer jam 945" (summer jam 945) [Trackback]
"auto lifts" (auto lifts) [Trackback]
"i ching" (i ching) [Trackback]
"factory authorized boat repair" (factory authorized boat repair) [Trackback]
"Online Trading" (Online Trading) [Trackback]
"lion king rochester ny" (lion king rochester ny) [Trackback]
"window trim" (window trim) [Trackback]
"hair loss propecia" (hair loss propecia) [Trackback]
"gradito moglie gruppo" (gradito moglie gruppo) [Trackback]
"kentucky limos" (kentucky limos) [Trackback]
"CAMP LIBERTY BELL%2C KOREA" (CAMP LIBERTY BELL%2C KOREA) [Trackback]
"pizza recipies" (pizza recipies) [Trackback]
"ragazzo mont saint michel" (ragazzo mont saint michel) [Trackback]
"wn1151 tag heuer" (wn1151 tag heuer) [Trackback]
"electronic timesheet" (electronic timesheet) [Trackback]
"guideline HIV AIDS Treatments" (guideline HIV AIDS Treatments) [Trackback]
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):