问题介绍
网站运行的时候是否遇到过未处理异常(unhandled exception)造成网站进程退出报503(service unavailable)错误?但是也有时未处理异常仅仅是在页面上显示出错信息,网站进程还在照常运行。
- 为什么同样发生了异常,结果却截然不同?
- 这种问题该如何调试?
这片文章通过调试试验来揭开这些问题的答案。
第一种情况
ASP.NET网站运行过程中莫名其妙的退出,在系统事件日志中会有如下记录。
Log Name: System Source: Microsoft-Windows-WAS Date: 10/6/2012 5:20:03 PM Event ID: 5011 Task Category: None Level: Warning Keywords: Classic User: N/A Computer: system-02 Description: A process serving application pool 'xxx' suffered a fatal communication error with the Windows Process Activation Service. The process id was '5284'. The data field contains the error number.应用程序日志中有ASP.NET的错误消息
An unhandled exception occurred and the process was terminated. Application ID: /LM/W3SVC/2/ROOT Process ID: 3016 Exception: System.Exception Message: Exception of type 'System.Exception' was thrown. StackTrace: at ASP.backgroundexception_aspx.CrashSite(Object arg) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 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)如果这种错误很短时间内出现次数过多的话,接下来网站就不能访问了,直接返回这样的页面。(这是因为IIS默认提供出错保护,默认情况下在5分钟内出错5次就会自动停掉程序池)
系统日志中也会有这么一条记录。
Log Name: System Source: Microsoft-Windows-WAS Date: 10/6/2012 6:50:53 PM Event ID: 5002 Task Category: None Level: Error Keywords: Classic User: N/A Computer: system-02 Description: Application pool 'xxx' is being automatically disabled due to a series of failures in the process(es) serving that application pool.
第二种情况
网站同样报出异常,服务器返回错误页面。
应用程序日志中记录为一个警告,当时系统日志中并没有相应的错误。w3wp进程也没有退出。
Log Name: Application Source: ASP.NET 2.0.50727.0 Date: 10/6/2012 5:54:53 PM Event ID: 1309 Task Category: Web Event Level: Warning Keywords: Classic User: N/A Computer: system-02 Description: Event code: 3005 Event message: An unhandled exception has occurred. Event time: 10/6/2012 5:54:53 PM Event time (UTC): 10/6/2012 9:54:53 AM Event ID: 55545893cefc429d895523e8aadc3e01 Event sequence: 12 Event occurrence: 3 Event detail code: 0 Application information: Application domain: /LM/W3SVC/2/ROOT-1-129939906465074620 Trust level: Full Application Virtual Path: / Application Path: C:\inetpub\webdebug\ Machine name: DOFWIN8-02 Process information: Process ID: 3016 Process name: w3wp.exe Account name: NT AUTHORITY\LOCAL SERVICE Exception information: Exception type: Exception Exception message: Exception of type 'System.Exception' was thrown. Request information: Request URL: http://localhost:8080/ForegroundException.aspx Request path: /ForegroundException.aspx User host address: ::1 User: Is authenticated: False Authentication Type: Thread account name: NT AUTHORITY\LOCAL SERVICE Thread information: Thread ID: 6 Thread account name: NT AUTHORITY\LOCAL SERVICE Is impersonating: False Stack trace: at ASP.foregroundexception_aspx.Page_Load(Object sender, EventArgs e) at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
调试试验
首先我们来查看并没有造成进程退出的异常页面。通过windbg连接到w3wp进程,然后捕获所有的CLR
first chance exception(命令 sxe clr),然后请求这个网页。马上在windbg中我们被通知有异常发生。
(24.119c): CLR exception - code e0434f4d (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. KERNELBASE!RaiseException+0x68: 000007fe`a84089cc 488b8c24c0000000 mov rcx,qword ptr [rsp+0C0h] ss:00000071`612edf70=00006cb2cdfa4031线程调用栈如下
0:019> !dumpstack OS Thread Id: 0x119c (19) Child-SP RetAddr Call Site 00000071612edeb0 000007fe86d398ef KERNELBASE!RaiseException+0x68 00000071612edf90 000007fe87224340 mscorwks!RaiseTheExceptionInternalOnly+0x2ff 00000071612ee080 000007fe27570972 mscorwks!JIT_Throw+0x130 00000071612ee230 000007fe275d0f39 App_Web_qq7atv_i!ASP.foregroundexception_aspx.Page_Load(System.Object, System.EventArgs)+0x52 00000071612ee270 000007fe7c659f8a System_Web_RegularExpressions!System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs)+0x19 00000071612ee2a0 000007fe7c650744 System_Web_ni!System.Web.Util.CalliEventHandlerDelegateProxy.Callback(System.Object, System.EventArgs)+0x2a 00000071612ee2d0 000007fe7c6507a2 System_Web_ni!System.Web.UI.Control.OnLoad(System.EventArgs)+0x84 00000071612ee310 000007fe7c64cd2c System_Web_ni!System.Web.UI.Control.LoadRecursive()+0x42 00000071612ee360 000007fe7c64c230 System_Web_ni!System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)+0x97c 00000071612ee430 000007fe7c64c15b System_Web_ni!System.Web.UI.Page.ProcessRequest(Boolean, Boolean)+0xa0 00000071612ee490 000007fe7c64c0f0 System_Web_ni!System.Web.UI.Page.ProcessRequest()+0x5b 00000071612ee4f0 000007fe275702f4 System_Web_ni!System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)+0xf0 00000071612ee550 000007fe7c653597 App_Web_qq7atv_i!ASP.foregroundexception_aspx.ProcessRequest(System.Web.HttpContext)+0x34 00000071612ee580 000007fe7c61675b System_Web_ni!System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+0x257 00000071612ee630 000007fe7cd04bc1 System_Web_ni!System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)+0xab 00000071612ee6d0 000007fe7ccf54b2 System_Web_ni!System.Web.HttpApplication+PipelineStepManager.ResumeSteps(System.Exception)+0x511 00000071612ee860 000007fe7ccd6f69 System_Web_ni!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext, System.AsyncCallback)+0x72 00000071612ee8b0 000007fe7cdfebc1 System_Web_ni!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)+0x269 00000071612ee9d0 000007fe7cdfe78b System_Web_ni!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)+0x411 00000071612eeb50 000007fe7cdfe3c4 System_Web_ni!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)+0x2b 00000071612eebb0 000007fe86ddb0ca System_Web_ni!DomainNeutralILStubClass.IL_STUB(Int64, Int64, Int64, Int32)+0x24 ... 00000071612efad0 000007fe994c11f6 webengine!W3_MGD_HANDLER::ProcessNotification+0x107 00000071612efb20 000007fe86c975f7 webengine!ProcessNotificationCallback+0x46 00000071612efb50 000007fe86ca970a mscorwks!UnManagedPerAppDomainTPCount::DispatchWorkItem+0x157 00000071612efbf0 000007fe86d5f3a4 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x1ba 00000071612efc90 000007feaa62167e mscorwks!Thread::intermediateThreadProc+0x78 00000071612efe60 000007feab35c3f1 KERNEL32!BaseThreadInitThunk+0x1a 00000071612efe90 0000000000000000 ntdll!RtlUserThreadStart+0x1d
我们直接接下来我们将会收到一个错误页面包含了相应的异常信息,可以推断出来很有可能是这个逻辑调用栈中哪里捕获了这个异常,并且将异常信息写成了html网页发回给了客户端。但是怎么验证这个猜想是个难题,一步一步按照这个调用栈看上去很难发现,因为里面逻辑分支过多(这种方法我尝试过并且放弃了) 这里我们看到错误页面上显示了异常的调用栈信息,这告诉我们这个HttpResponse一定访问了异常调用栈信息,如果我们在调用栈信息的地址加一个访问断点,服务器在组织给客户端回复的过程中的调用过程就可以被我们抓到。
首先我们找到这个异常
0:018> !do 000000a80010e090 Name: System.Exception MethodTable: 000007fe7e0b7ee8 EEClass: 000007fe7dcbe6b0 Size: 136(0x88) bytes GC Generation: 0 (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) Fields: MT Field Offset Type VT Attr Value Name 000007fe7e0b7c20 40000b5 8 System.String 0 instance 0 _className 000007fe7e0b5fc8 40000b6 10 ...ection.MethodBase 0 instance 0 _exceptionMethod 000007fe7e0b7c20 40000b7 18 System.String 0 instance 0 _exceptionMethodString 000007fe7e0b7c20 40000b8 20 System.String 0 instance 0 _message 000007fe7e0af240 40000b9 28 ...tions.IDictionary 0 instance 0 _data 000007fe7e0b7ee8 40000ba 30 System.Exception 0 instance 0 _innerException 000007fe7e0b7c20 40000bb 38 System.String 0 instance 0 _helpURL 000007fe7e0b7510 40000bc 40 System.Object 0 instance a80010e2b0 _stackTrace 000007fe7e0b7c20 40000bd 48 System.String 0 instance 0 _stackTraceString 000007fe7e0b7c20 40000be 50 System.String 0 instance 0 _remoteStackTraceString 000007fe7e0bee90 40000bf 70 System.Int32 1 instance 0 _remoteStackIndex 000007fe7e0b7510 40000c0 58 System.Object 0 instance 0 _dynamicMethods 000007fe7e0bee90 40000c1 74 System.Int32 1 instance -2146233088 _HResult 000007fe7e0b7c20 40000c2 60 System.String 0 instance 0 _source 000007fe7e0ba628 40000c3 68 System.IntPtr 1 instance 0 _xptrs 000007fe7e0bee90 40000c4 78 System.Int32 1 instance -532459699 _xcode
加访问断点然后运行,
ba r4 a80010e2b0果然断下来了,
0:018> g Breakpoint 1 hit mscorwks!ArrayBase::GetDataPtr+0x5: 000007fe`86d06da5 0f85c5312700 jne mscorwks! ?? ::FNODOBFM::`string'+0x6ae0 (000007fe`86f79f70) [br=0]
0:018> !dumpstack OS Thread Id: 0x860 (18) *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\mscorlib\da1374321aba580a5d2ec1c436b7f627\mscorlib.ni.dll Child-SP RetAddr Call Site 000000a859b1da48 000007fe86c50779 mscorwks!ArrayBase::GetDataPtr+0x5 000000a859b1da50 000007fe86c8af58 mscorwks!StackTraceArray::Size+0x15 000000a859b1da80 000007fe872a1423 mscorwks!DebugStackTrace::GetStackFramesFromException+0x6c 000000a859b1db10 000007fe7dfce723 mscorwks!DebugStackTrace::GetStackFramesInternal+0x1c3 000000a859b1e070 000007fe7dfce6bc mscorlib_ni!System.Diagnostics.StackTrace.CaptureStackTrace(Int32, Boolean, System.Threading.Thread, System.Exception)+0x53 000000a859b1e0d0 000007fe7c5dcede mscorlib_ni!System.Diagnostics.StackTrace..ctor(System.Exception, Boolean)+0x2c 000000a859b1e120 000007fe7c5dce5c System_Web_ni!System.Web.Management.WebThreadInformation..ctor(System.Exception)+0x5e 000000a859b1e160 000007fe7c66f5fd System_Web_ni!System.Web.Management.WebRequestErrorEvent.PreProcessEventInit()+0x3c 000000a859b1e1a0 000007fe7c61c72a System_Web_ni!System.Web.Management.WebBaseEvent.RaiseInternal(System.Web.Management.WebBaseEvent, System.Collections.ArrayList, Int32, Int32)+0x31d 000000a859b1e310 000007fe7c66ebe1 System_Web_ni!System.Web.Management.WebBaseEvent.RaiseSystemEventInternal(System.String, System.Object, Int32, Int32, System.Exception, System.String)+0x17a 000000a859b1e3b0 000007fe7c645cff System_Web_ni!System.Web.Management.WebBaseEvent.RaiseRuntimeError(System.Exception, System.Object)+0x101 000000a859b1e430 000007fe7cccd9c6 System_Web_ni!System.Web.HttpResponse.ReportRuntimeError(System.Exception, Boolean, Boolean)+0x6f 000000a859b1e490 000007fe7ccd6c38 System_Web_ni!System.Web.HttpContext.ReportRuntimeErrorIfExists(System.Web.RequestNotificationStatus ByRef)+0x256 000000a859b1e520 000007fe7ccd6fec System_Web_ni!System.Web.HttpRuntime.FinishRequestNotification(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext, System.Web.RequestNotificationStatus ByRef)+0x58 000000a859b1e590 000007fe7cdfebc1 System_Web_ni!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)+0x2ec 000000a859b1e6b0 000007fe7cdfe78b System_Web_ni!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)+0x411 000000a859b1e830 000007fe7cdfe3c4 System_Web_ni!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)+0x2b ... 000000a859b1f800 000007fe86c975f7 webengine!ProcessNotificationCallback+0x46 000000a859b1f830 000007fe86ca970a mscorwks!UnManagedPerAppDomainTPCount::DispatchWorkItem+0x157 000000a859b1f8d0 000007fe86d5f3a4 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x1ba 000000a859b1f970 000007feaa62167e mscorwks!Thread::intermediateThreadProc+0x78 000000a859b1fb40 000007feab35c3f1 KERNEL32!BaseThreadInitThunk+0x1a 000000a859b1fb70 0000000000000000 ntdll!RtlUserThreadStart+0x1d
根据这个调用栈信息我们就可以看到异常全被catch住加到了context的Error中,最后通过接下来的调用栈组织回复发送给客户端。
private RequestNotificationStatus ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) { RequestNotificationStatus requestNotificationStatus = RequestNotificationStatus.Pending; try { //处理逻辑省略 } catch (Exception errorInfo) { requestNotificationStatus = RequestNotificationStatus.FinishRequest; context.Response.InitResponseWriter(); context.AddError(errorInfo); } if (requestNotificationStatus != RequestNotificationStatus.Pending) { this.FinishRequestNotification(wr, context, ref requestNotificationStatus); } return requestNotificationStatus; }
至此第一个问题我们解决了一半。接下来看第二个造成进程推出的请求。
同样的调试流程,断点first chance exception,发生第一次异常
(3ac.860): CLR exception - code e0434f4d (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. KERNELBASE!RaiseException+0x68: 000007fe`a84089cc 488b8c24c0000000 mov rcx,qword ptr [rsp+0C0h] ss:000000a8`59b1e4a0=00003fce0bb4ed87 0:018> !pe Exception object: 000000a80013e0e0 Exception type: System.Exception Message: <none> InnerException: <none> StackTrace (generated): <none> StackTraceString: <none> HResult: 80131500 0:018> !dumpstack OS Thread Id: 0x860 (18) Child-SP RetAddr Call Site 000000a859b1e3e0 000007fe86d398ef KERNELBASE!RaiseException+0x68 000000a859b1e4c0 000007fe87224340 mscorwks!RaiseTheExceptionInternalOnly+0x2ff 000000a859b1e5b0 000007fe275612dd mscorwks!JIT_Throw+0x130 000000a859b1e760 000007fe7df8dc78 App_Web_qq7atv_i!ASP.backgroundexception_aspx.CrashSite(System.Object)+0x4d 000000a859b1e7a0 000007fe86ddd552 mscorlib_ni!System.Threading.ExecutionContext.runTryCode(System.Object)+0x178 000000a859b1e860 000007fe86d1a283 mscorwks!CallDescrWorker+0x82 000000a859b1e8b0 000007fe871bc7af mscorwks!CallDescrWorkerWithHandler+0xd3 000000a859b1e950 000007fe86d13412 mscorwks!MethodDesc::CallDescr+0x2af 000000a859b1eba0 000007fe8723bcb2 mscorwks!ExecuteCodeWithGuaranteedCleanupHelper+0x12a 000000a859b1ee30 000007fe7df72ba2 mscorwks!ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup+0x172 000000a859b1f040 000007fe7dfe74b1 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x62 000000a859b1f090 000007fe7dfe72ef mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(System.Threading._ThreadPoolWaitCallback)+0x61 000000a859b1f0e0 000007fe86ddd552 mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(System.Object)+0x4f 000000a859b1f130 000007fe86d1a283 mscorwks!CallDescrWorker+0x82 000000a859b1f180 000007fe86d1a3ca mscorwks!CallDescrWorkerWithHandler+0xd3 000000a859b1f220 000007fe86d504c7 mscorwks!DispatchCallDebuggerWrapper+0x3e 000000a859b1f280 000007fe86c195cf mscorwks!DispatchCallNoEH+0x5f 000000a859b1f300 000007fe86d5cda4 mscorwks!QueueUserWorkItemManagedCallback+0x83 000000a859b1f390 000007fe86d43721 mscorwks!CClosedHashEx<CCustAttrHashKey,CCustAttrHash>::Hash+0x30 000000a859b1f3e0 000007fe86c3fc59 mscorwks!CNgenEntryBind::Create+0x15d 000000a859b1f4b0 000007fe86d69c4d mscorwks!ThreadExceptionState::GetFlags+0x79 000000a859b1f4f0 000007fe86d5cf31 mscorwks!SharedFileLockHolderBase::DoRelease+0x4d 000000a859b1f520 000007fe86d5cdc9 mscorwks!Thread::DoADCallBack+0x145 000000a859b1f690 000007fe86d43721 mscorwks!CClosedHashEx<CCustAttrHashKey,CCustAttrHash>::Hash+0x55 000000a859b1f6e0 000007fe86c3fc59 mscorwks!CNgenEntryBind::Create+0x15d 000000a859b1f7b0 000007fe86c48993 mscorwks!ThreadExceptionState::GetFlags+0x79 000000a859b1f7f0 000007fe86ca970a mscorwks!ManagedPerAppDomainTPCount::DispatchWorkItem+0x12b 000000a859b1f8d0 000007fe86d5f3a4 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x1ba 000000a859b1f970 000007feaa62167e mscorwks!Thread::intermediateThreadProc+0x78 000000a859b1fb40 000007feab35c3f1 KERNEL32!BaseThreadInitThunk+0x1a 000000a859b1fb70 0000000000000000 ntdll!RtlUserThreadStart+0x1d这里我们看到这个线程并不是一个处理请求的线程,而是线程池中的一个后台线程调用了我们页面逻辑抛出了异常。那这个异常有相应的处理方法么?接下来继续运行。
(3ac.860): CLR exception - code e0434f4d (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. KERNELBASE!RaiseException+0x68: 000007fe`a84089cc 488b8c24c0000000 mov rcx,qword ptr [rsp+0C0h] ss:000000a8`59b1f100=00003fce0bb4fe27 0:018> !dumpstack OS Thread Id: 0x860 (18) Child-SP RetAddr Call Site 000000a859b1f040 000007fe86d398ef KERNELBASE!RaiseException+0x68 000000a859b1f120 000007fe870832e7 mscorwks!RaiseTheExceptionInternalOnly+0x2ff 000000a859b1f210 000007fe870854c6 mscorwks!RaiseTheException+0x57 000000a859b1f240 000007fe87108315 mscorwks!BStrFromString+0x66 000000a859b1f270 000007fe8710832b mscorwks!RealCOMPlusThrow+0x35 000000a859b1f2e0 000007fe87128b56 mscorwks!RealCOMPlusThrow+0xb 000000a859b1f310 000007fe86fce2e8 mscorwks!Thread::RaiseCrossContextException+0x2d6 000000a859b1f520 000007fe86d5cdc9 mscorwks! ?? ::FNODOBFM::`string'+0x5ae58 000000a859b1f690 000007fe86d43721 mscorwks!CClosedHashEx<CCustAttrHashKey,CCustAttrHash>::Hash+0x55 000000a859b1f6e0 000007fe86c3fc59 mscorwks!CNgenEntryBind::Create+0x15d 000000a859b1f7b0 000007fe86c48993 mscorwks!ThreadExceptionState::GetFlags+0x79 000000a859b1f7f0 000007fe86ca970a mscorwks!ManagedPerAppDomainTPCount::DispatchWorkItem+0x12b 000000a859b1f8d0 000007fe86d5f3a4 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x1ba 000000a859b1f970 000007feaa62167e mscorwks!Thread::intermediateThreadProc+0x78 000000a859b1fb40 000007feab35c3f1 KERNEL32!BaseThreadInitThunk+0x1a 000000a859b1fb70 0000000000000000 ntdll!RtlUserThreadStart+0x1d 0:018> g (3ac.860): CLR exception - code e0434f4d (!!! second chance !!!) KERNELBASE!RaiseException+0x68: 000007fe`a84089cc 488b8c24c0000000 mov rcx,qword ptr [rsp+0C0h] ss:000000a8`59b1f100=00003fce0bb4fe27 0:018> !dumpstack OS Thread Id: 0x860 (18) Child-SP RetAddr Call Site 000000a859b1f040 000007fe86d398ef KERNELBASE!RaiseException+0x68 000000a859b1f120 000007fe870832e7 mscorwks!RaiseTheExceptionInternalOnly+0x2ff 000000a859b1f210 000007fe870854c6 mscorwks!RaiseTheException+0x57 000000a859b1f240 000007fe87108315 mscorwks!BStrFromString+0x66 000000a859b1f270 000007fe8710832b mscorwks!RealCOMPlusThrow+0x35 000000a859b1f2e0 000007fe87128b56 mscorwks!RealCOMPlusThrow+0xb 000000a859b1f310 000007fe86fce2e8 mscorwks!Thread::RaiseCrossContextException+0x2d6 000000a859b1f520 000007fe86d5cdc9 mscorwks! ?? ::FNODOBFM::`string'+0x5ae58 000000a859b1f690 000007fe86d43721 mscorwks!CClosedHashEx<CCustAttrHashKey,CCustAttrHash>::Hash+0x55 000000a859b1f6e0 000007fe86c3fc59 mscorwks!CNgenEntryBind::Create+0x15d 000000a859b1f7b0 000007fe86c48993 mscorwks!ThreadExceptionState::GetFlags+0x79 000000a859b1f7f0 000007fe86ca970a mscorwks!ManagedPerAppDomainTPCount::DispatchWorkItem+0x12b 000000a859b1f8d0 000007fe86d5f3a4 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x1ba 000000a859b1f970 000007feaa62167e mscorwks!Thread::intermediateThreadProc+0x78 000000a859b1fb40 000007feab35c3f1 KERNEL32!BaseThreadInitThunk+0x1a 000000a859b1fb70 0000000000000000 ntdll!RtlUserThreadStart+0x1d最终证明没有可以handle这个异常的处理方法,Second chance exception发生,意味着进程终止。
也就是说,.NET Framework对于未处理异常(unhandled exception)的方式是让他抛出去,crash就crash。如果第一种情况没有System.Web.HttpRuntime的异常处理逻辑,那么第一个页面也会导致进程退出。实际上,这种机制在.NET Framework 1.1版本的时候处理方式是不一样的,之前的处理方式是将unhandled exception吃掉,但这种方式的风险在于真正的逻辑除了问题的时候无从知晓,反而加大了调试难度。所以在.NET Framework 2.0将这种方式改为直接抛出。
当然这里还有一个回到过去的办法,就是更改如下配置,异常将会不再造成crash。
<configuration> <runtime> <legacyUnhandledExceptionPolicy enabled="true" /> </runtime> </configuration>
解决办法
对于这个问题的调试方法相对来说就简单很多,只要我们知道异常的调用栈信息,这个问题就很明了了,所以我们可以通过以下两种方式抓到这个信息。
第一种,把异常调用栈信息记录在日志里,参考这个链接
http://support.microsoft.com/kb/911816/zh-cn
第二种,抓crash dump,各种工具都可以用,
Adplus - http://support.microsoft.com/kb/286350
Windbg - 异常断电 + .dump /ma c:\dumps\youdumpname.dmp
Debugdiag - http://support.microsoft.com/kb/919789/zh-cn