Posts Tagged ‘Crash’

ASP.NET App Slow Response and Application Pool/AppDomain Recycle, Event message: Application is shutting down. Reason: Unknown - Windows Server 2003

Sunday, August 30th, 2009

Scenario
From time to time, asp.net application response is very slow on Windows Server 2003

Some rants and the resolution

After turning on recycle events, logged message in application event log was Event message: Application is shutting down. Reason: Unknown. Slow response is always timed with this message in the application event log so that confirmed that Application Pool is terminating so no wonder asp.net response is slow from time to time.

However, the only missing piece was why? Since, the Reason is unknown :-). This application pool is configured for web garden with 6 app pools in it so we decided to attach debugger in production box to 2 worker processes.

If you are just starting out with debugging or have not read John Robbins Book on debugging, I would like to stress the followings when using debugger in production environment

1. By Default, ADPlus  writes the call stack on first-chance exception. Walking call stack also results in Symbol loading, symbol loading along with the stack walking causes a performance hit when a debugger is attached. The last thing you want in production environment is to cause performance hit because of  debugger.

2. Don’t just use ADPlus script to attach a debugger to the worker process by name because it will attach the debugger to each worker process in your production server causing  further performance hit.

3. Don’t use DebugDiag in production environment unless you really have a good reason for it.

The reason I am stressing about these points is because I noticed someone following all the worst practices in production environment while debugging.

The best practice is to use adplus configuration file to attach to a worker process and preferably by worker process id.

Identifying the issue

First of all, I would like to mention that Tess has excellent blog on AppDomain recycle http://blogs.msdn.com/tess/archive/2006/08/02/asp-net-case-study-lost-session-variables-and-appdomain-recycles.aspx

We just needed to find out the reason for AppPool shutdown.

Our goal is to attach a debugger to one worker process to generate a memory dump on crash and another goal is, ctrl+c in debugger console should not kill the worker process. We used optimized ADPlus Config file for production environment as shown below

<ADPlus>
<Settings>
<RunMode>CRASH</RunMode>
<Option>Quiet</Option>
<OutputDir> c:\dumps </OutputDir>
<ProcessID> 2684 </ProcessID>
</Settings>
<Exceptions>
<Option>   NoDumpOnFirstChance    </Option>
<Config>
<Code>    AllExceptions    </Code>
<Actions1>     Log     </Actions1>
<Actions2>    FullDump;  </Actions2>
<ReturnAction1>    GN    </ReturnAction1>
<ReturnAction2>   Q   </ReturnAction2>
</Config>
</Exceptions>
</ADPlus>

once we have the crash dump, just dump the httpruntime object to find out the shutdown reason and the call stack as shown below

at System.Web.HttpRuntime.ShutdownAppDomain(String stackTrace)
at System.Web.HttpRuntime.OnCriticalDirectoryChange(Object sender, FileChangeEvent e)
at System.Web.FileChangesMonitor.OnSubdirChange(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.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
ShutDownReason in memory dumps
0:005> !do 06e6c82c
Name: System.String
MethodTable: 79330a00
EEClass: 790ed64c
Size: 67576(0×107f8) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: Directory rename change notification for ‘C:\Inetpub\<>\<>’.
Web dir change or directory renameAppDomain is shutting down because of directory rename.

There are thousands of folders under the root website and after talking to customer I learnt that this is indeed the case.

Resolution

After googling or binging, I found out that there is no resolution and this was implemented in asp.net 2.0. AppDomain will recycle on directory rename or delete. However, I did come across a
Microsoft KB http://support.microsoft.com/kb/911272 which talks about changing this behavior from registry setting. The bad news is changing the registry setting [HKEY_LOCAL_MACHINE\SOFTWARE\
ASP.NET\"FCNMode"=dword:00000001 doesn't work. Although, KB article does suggest you to contact Microsoft support for hot fix but also suggests that it will be addressed in the next .NET SP.

The point is registry setting didn't work and below is what I found after looking at the HttpRuntime implementation in reflector.
System.HttpRuntime implements the following events for shut down
OnFileChange(FileAction, String, DateTime)
OnCriticaldirChange(Object, FileChangeEvent)
OnSubdirChange(Object, FileChangeEvent)

Another cause of AppDomain recycle is overwhelming amount of file change notification but microsoft apparently fixed in .net 2.0 hot fix so who knows.

HttpRuntime also implements another method to monitor the directories

internal void StartListeningToLocalResourcesDirectory(VirtualPath virtualDir)

{
    if (!this.IsFCNDisabled && ((this._callbackRenameOrCriticaldirChange != null) && (this._dirMonSpecialDirs != null)))

    {

You will notice, how it checks for FCNDisabled which should have been the registry key since it return (this._FCNMode == 1);

All these settings are set in
internal
FileChangesMonitor() { UnsafeNativeMethods.GetDirMonConfiguration(out this._FCNMode);

FCNMode value comes from native dll (webengine.dll)

[DllImport("webengine.dll")]
internal static extern void GetDirMonConfiguration(out int FCNMode);
So the only reason, I can think of why registry setting is not working is the file version of “webengine.dll”. In Microsoft KB the file version of webengine.dll is 2.0.50727.62 which is different than what we have in production box.
After searching more on httpruntime on internet, I came across a post on http://forums.asp.net/p/1310976/2581558.aspx where someone has suggested the workaround using reflection as shown below.

Since, HttpRuntime controls the file monitoring so get the DirectoryMonitor object and calls StopMonitoring on it. Another way to probably implement is getting the FileChangesMonitor object and setting the FCNMode to 1 or setting the _dirMonSpecialDirs to null.

protected void Application_Start(object sender, EventArgs e)
{
System.Reflection.PropertyInfo p = typeof(System.Web.HttpRuntime)

.GetProperty(”FileChangesMonitor”,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

object o = p.GetValue(null, null);
System.Reflection.FieldInfo f = o.GetType().GetField(”_dirMonSubdirs”,
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.IgnoreCase);

object monitor = f.GetValue(o);

System.Reflection.MethodInfo m = monitor.GetType().GetMethod(”StopMonitoring”,
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
m.Invoke(monitor, null);
}

Application Shutdown Unknown Message
I found a piece of code in Scotgu blog to log shutdown events using reflection in Global.asax code behind, below is the code. You will notice that it uses the _shutDownMessage and _shutDownStack member of HttpRuntime object to log the message and the stack.
This implementation saves you from looking at the crash dump and dumping the HttpRuntime object to find the exact shutdown message.
protected void Application_End(object sender, EventArgs e)
{
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);
}

Important Note

Microsoft KB http://support.microsoft.com/kb/911272 which talks about changing this behavior from registry setting doesn’t work in Windows Server 2003 but it does work on Windows Server 2008/R2 with IIS7 integrated/classic pipeline. The best way to address this issue is by modifying the registry key otherwise file handles don’t get released when dirMonSpecialDirs is set to null using reflection

Share/Save/Bookmark

win32 console app catch block not catching the Access Violation exception - Why SEH(Structured Exception Handling) not working in a win32 C++ app

Friday, March 27th, 2009

Description

I created a simple win32 console application using visual studio 2008, below is the code

class Person
{
private:
char* m_szFirstName;
char* m_szMiddleInitial;
public:
Person(char* szFirstName, char* szMiddleInitial)

{

m_szFirstName = szFirstName;m_szMiddleInitial = szMiddleInitial

}
char* FirstName(){return m_szFirstName;}
char* MiddleInitial(){return m_szMiddleInitial;}
};

int _tmain(int argc, _TCHAR* argv[])
{
Person* pPerson = new Person(”David”,NULL);
char msg[100];
try
{
sprintf_s(msg,”First Name = %s, Middle Initial = %s\n”, pPerson->FirstName(), pPerson->MiddleInitial());
}
catch(…)
{
sprintf_s(msg,”Exception Occured\n”);
}
printf(msg);
delete pPerson;
printf(”press key to exit”);
char* key;
scanf_s(”%c”, key);
return 0;
}

When I run this app, it crashes with Unhandled Exception - Access Violation, although I do have a catch all exception block - catch(…)

Analysis

I disassembled main function and below is what I noticed

Section .text (0×00401000)
;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
; SYM:wmain <Int>
0×401000: 83EC6C                 SUB         ESP,0×6C           ; <==0×00401207(*+0×207)
0×401003: A100304000         MOV         EAX,DWORD PTR [__security_cookie <UInt>]; (0×403000); .data:0×4E 0xE6 0×40 0xBB
0×401008: 33C4                     XOR         EAX,ESP
0×40100A: 89442468             MOV         DWORD PTR [ESP+0x68],EAX
0×40100E: 56                          PUSH        ESI
0×40100F: 57                          PUSH        EDI
0×401010: 6A08                      PUSH        0×8
0×401012: E88F000000           CALL        __imp_??2@YAPAXI@Z ; (0×4010A6) ; operator new

In case you don’t know the internals of Win32 Structured Exception handling(SEH), please read A Crash Course on the Depths of Win32™ Structured Exception Handling by Matt Pietrek. You will notice the missing instruction to move DWORD pointer from FS:[0x0] register. FS:[0x00] -  4 bytes points to the current Structured Exception Handling (SEH) frame for each thread. Win32 SEH works on a per thread basis with each thread having its own exception handler callback function. On Intel machine, FS register points to the current TEB(Thread Environment Block). That’s why in SEH code, you will have a instruction to move DWORD ptr from FS:[0] register because that’s where you have a pointer to an EXCEPTION_REGISTRATION structure.

Why is it MISSING???

It turns out, visual studio 2008 default settings compiles with “Enable C++ Exception /EHsc” switch which will catch only c++ exceptions also called synchronous exceptions. More information on Exception handling model here http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80).aspx Once you change the compiler switch to /EHa, everything is good as shown below

0×401000: 55                       PUSH        EBP                ; <==0×00401267(*+0×267)
0×401001: 8BEC                   MOV         EBP,ESP
0×401003: 6AFF                   PUSH        0xFF
0×401005: 681B194000       PUSH        __CxxFrameHandler3 + 0×001D; (0×40191B); .text:0×8B 0×54 0×24 0×08
0×40100A: 64A100000000  MOV         EAX,DWORD PTR FS:[0x0]

Share/Save/Bookmark

Akismet - Spam Blocked
March 2010
M T W T F S S
« Feb    
1234567
891011121314
15161718192021
22232425262728
293031  
Categories