Sunday, May 06, 2007

From time to time the ASPNET worker process just conks out..

This little snippet will tell you why.

http://weblogs.asp.net/scottgu/archive/2005/12/14/433194.aspx


extracted from the site..

Logging ASP.NET Application Shutdown Events


Someone on a listserv recently asked whether there was a way to figure out why and when ASP.NET restarts application domains. Specifically, he was looking for the exact cause of what was triggering them on his application in a production shared hosted environment (was it a web.config file change, a global.asax change, an app_code directory change, a directory delete change, max-num-compilations reached quota, \bin directory change, etc).

Thomas on my team has a cool code-snippet that he wrote that uses some nifty private reflection tricks to capture and log this information. It is pretty easy to re-use and add into any application, and can be used to log the information anywhere you want (the below code use the NT Event Log to save it – but you could just as easily send it to a database or via an email to an admin). The code works with both ASP.NET V1.1 and ASP.NET V2.0.

Simply add the System.Reflection and System.Diagnostics namespaces to your Global.asax class/file, and then add the Application_End event with this code (note: you can also download a .zip file containing the code from here):

public void Application_End() {

HttpRuntime runtime = (HttpRuntime) typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime",

BindingFlags.NonPublic

BindingFlags.Static

BindingFlags.GetField,

null,

null,

null);

if (runtime == null)

return;

string shutDownMessage = (string) runtime.GetType().InvokeMember("_shutDownMessage",

BindingFlags.NonPublic

BindingFlags.Instance

BindingFlags.GetField,

null,

runtime,

null);

string shutDownStack = (string) runtime.GetType().InvokeMember("_shutDownStack",

BindingFlags.NonPublic

BindingFlags.Instance

BindingFlags.GetField,

null,

runtime,

null);

if (!EventLog.SourceExists(".NET Runtime")) {

EventLog.CreateEventSource(".NET Runtime", "Application");

}

EventLog log = new EventLog();

log.Source = ".NET Runtime";

log.WriteEntry(String.Format("\r\n\r\n_shutDownMessage={0}\r\n\r\n_shutDownStack={1}",

shutDownMessage,

shutDownStack),

EventLogEntryType.Error);

}

I tried this out using a simple web-site using ASP.NET 2.0 and the built-in VS Web-Server (aka Cassini). When I changed the web.config file in my running application, the following was logged to my "Application" event viewer:

_shutDownMessage=CONFIG change

HostingEnvironment caused shutdown

CONFIG change

CONFIG change

_shutDownStack= at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)

at System.Environment.get_StackTrace()

at System.Web.HttpRuntime.ShutdownAppDomain()

at System.Web.Hosting.HostingEnvironment.ShutdownThisAppDomainOnce()

at System.Web.Hosting.HostingEnvironment.InitiateShutdownWorkItemCallback(Object state)

at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state).

When I updated my Global.asax file with some code change, the following was logged:

_shutDownMessage=Change in GLOBAL.ASAX

Change in GLOBAL.ASAX

Change in GLOBAL.ASAX

HostingEnvironment caused shutdown

_shutDownStack= at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)

at System.Environment.get_StackTrace()

at System.Web.HttpRuntime.ShutdownAppDomain()

at System.Web.HttpApplicationFactory.OnAppFileChange(Object sender, FileChangeEvent e)

at System.Web.DirectoryMonitor.FireNotifications()

at System.Web.Util.WorkItem.CallCallbackWithAssert(WorkItemCallback callback)

at System.Web.Util.WorkItem.OnQueueUserWorkItemCompletion(Object state)

at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state).

And when I changed the contents of my \bin directory I got:

_shutDownMessage=Change Notification for critical directories.

bin dir change or directory rename

HostingEnvironment caused shutdown

Directory rename change notification for 'E:\Unload'.

Unload dir change or directory rename

_shutDownStack= at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)

at System.Environment.get_StackTrace()

at System.Web.HttpRuntime.ShutdownAppDomain()

at System.Web.Hosting.HostingEnvironment.ShutdownThisAppDomainOnce()

at System.Web.Hosting.HostingEnvironment.InitiateShutdownWorkItemCallback(Object state)

at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading.

Hopefully this is a useful trick that you can re-use in your own applications to get better visibility into what is going on with them. If you are using ASP.NET 2.0, then you should definitely also investigate the new ASP.NET 2.0 Health Monitoring feature-set. This provides a rich eventing architecture for instrumenting your code, as well as raising notifications of issues to admins when they occur within your application. K. Scott Allen has written a good overview article of how this new feature-set works, and links to the MSDN documentation.

Hope this helps,

Scott




Published
Wednesday, December 14, 2005 11:04 PM
by
ScottGu






No comments: