1. 在WinDbg目录执行 adplus –crash –pn w3wp.exe –quiet
2. 在 IIS manager里面浏览 CompanyInformation.aspx 页面,在文本框内输入字符串,点击send。此时浏览器将尝试将得不到响应,最后出现空白页面,表明IIS进程crash了。
3. 观察生成的dump,发现只有一个first change的mini dump,没有full dump,没有second-chance的dump。这表明程序在第一次出现exception的时候就crash掉了,可能是一些比较严重的问题,比如heap corruption或者stack overflow。
4. 为了使用adplus能够抓到first chance的full dump,我们需要引入adplus的config文件。在重新浏览CompanyInformation页面以后,在WinDbg目录执行以下命令 adplus –pn w3wp.exe –c c:\crash.cfg
crash.cfg的内容为:
<ADPlus>
<Breakpoints> <NewBP> <Address> Kernel32!ExitProcess </Address> <Type> BP </Type> </NewBP> <NewBP> <Address> Kernel32!TerminateProcess </Address> <Type> BP </Type> </NewBP> <Config> <Address> AllBreakpoints </Address> <Actions> FullDump </Actions> <ReturnAction> QD </ReturnAction> </Config> </Breakpoints> <Exceptions><Config>
<Code> AllExceptions </Code> <Actions1> void </Actions1> <Actions2> Log;Stack </Actions2> </Config> <Config> <Code> AV </Code> <Actions1> Minidump </Actions1> </Config> </Exceptions> </ADPlus>
5. 再次reproduce问题以后,抓到的first chance的crash dump的如下:
6. 使用WinDbg打开dump文件,载入SOS,执行 !clrstack
可见程序是反复执行了Utility.WriteToLog方法和ExceptionHandler方法,最终导致栈溢出。
7. 查找程序源代码,在ExceptionHandler.cs这个文件里面找到如下代码:
在Utility.cs里面找到如下代码:
可见程序出现问题的原因是,两个静态方法,循环引用,最终导致栈溢出。
20110222补充:
Tess原文中提到了Process被shut down的三种情况:一是出现了2nd chance的 unhandled exception;二是进程被外部程序关闭;三是出现了严重的1st chance的exception导致程序被shutdown,这些exception包括heap corruption,stack overflow,fatal execution engine error和out of memory。其中进程被外部程序关闭或者出现严重的1st chance的错误导致进程退出的情况,都属于1st chance的情况。我们再进行debugging的时候,首先就是要判定是crash属于什么情况。对于这篇blog提到的情况,判定的逻辑如下:
1. 执行adplus -crash w3wp.exe -quiet之后,抓到的只有1st chance的dump而没有2nd chance的dump,排除第一种情况:unhandled exception导致进程crash。
2. 对于抓到的dump,使用WinDBG打开以后,当前活跃线程是0,执行kL得到如下结果:
可见这里是ThreadStart,这个线程只是一个普通的线程,而并非主线程。Tess的文章中提到,如果是crash的第二种原因,外部程序将进程结束,那么抓到的dump的活跃进程应该是主线程。而对于主线程,我们会看到WinMain函数入口点。
0:000> kLChildEBP RetAddr 0014fbfc 7d503faf ntdll!ZwTerminateProcess+0x120014fc38 7d503f5a kernel32!_ExitProcess+0x4b0014fc4c 79fd9e8f kernel32!ExitProcess+0x140014fe74 79f7479c mscorwks!SafeExitProcess+0x1570014ff10 79004fab mscorwks!HandleExitProcessHelper+0x270014ff10 79004fab mscoree!CorExitProcess+0x460014ff20 77bcaddb mscoree!CorExitProcess+0x460014ff2c 77bcaefb msvcrt!__crtExitProcess+0x290014ff5c 77bcaf52 msvcrt!doexit+0x810014ff70 01001a3c msvcrt!exit+0x11 0014ffc0 7d4e7d2a w3wp!wmainCRTStartup+0x144 0014fff0 00000000 kernel32!BaseProcessStart+0x28因此,我们可以判断出导致进程crash的原因是第三种:fatal 1st chance error。对于这种情况,我们要对1st chance的error抓一个full user dump。
本文提到了使用adplus抓取first chance导致程序被shut down的情况,如果要使用DebugDiag,可以在设置rule的时候添加Kernel32!ExitProcess和Kernel32!TerminateProcess两个断点抓取full user dump