在 WebService 中获取 StackOverflowException (ASP.NET)

Getting StackOverflowException in WebService (ASP.NET)

我有一个名为 ECService.asmx 的 WebService,其中包含 230 多个 WebMethod。 当我将这些方法分成几个 "asmx" 或注释掉一半代码时,WhosebugException 将不再发生。

根据 MSDN:

A WhosebugException exception is thrown when the execution stack overflows by having too many nested method calls.

我很确定我没有任何递归方法。 他们所做的只是 return 调用时的数据集,仅此而已。

所以我做了一些研究并确信使用任何工具来提取进程的完整用户转储 (iisexpress),然后使用 windbg 工具检查记录在其中的堆栈树。我尝试使用 Visual Studio 2017 的选项 "Debug> Save Dump As..." 捕获完整的用户转储:

kbn
.loadby sos clr
!CLRStack

然后我得到了这个

0:033> !CLRStack
OS Thread Id: 0x584 (33)
Child SP       IP Call Site
06b625a8 77a21d3c [FaultingExceptionFrame: 06b625a8] 
06b9ef00 77a21d3c [InlinedCallFrame: 06b9ef00] 
06b9f540 77a21d3c [InlinedCallFrame: 06b9f540] 
06b9f53c 65cce181 DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, System.Web.RequestNotificationStatus ByRef)
06b9f540 65c7b892 [InlinedCallFrame: 06b9f540] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
06b9f574 65c7b892 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
06b9f578 65c7b39f [InlinedCallFrame: 06b9f578] 
06b9f670 65c7b39f System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
06b9f748 05aeeb10 [ContextTransitionFrame: 06b9f748] 

但我几乎没有发现任何与 WhosebugException 相关的内容。老实说,到了这一步我已经不知道该怎么办了...

我也尝试使用调试诊断工具来捕获完整转储,但我设置的规则 "Crash rule for all IIS/COM+ related processes" 从未被触发。我做错了吗?如果有遗漏,我想提供更多信息。

(请原谅,由于业务敏感性,我可能无法包含完整文件。现在我在一家商业公司实习,经理问我不能通过任何机械解决方法来忽略这个问题.)

研究参考:

exception code: 0xc00000fd. Debugging a WhosebugException

Using windbg to solve problems

我现在没有可用的 .NET 堆栈溢出崩溃转储,但这是我的记忆:

!threads 命令应该列出 .NET 线程。如果某个线程出现异常,则该线程应该在 "Exception" 列中有一个指示符。使用 ~<number>s 切换到该线程,然后使用 !clrstack.

它也应该在本机端工作,因为 .NET 异常也是正常的 SEH 异常。如果你使用navtive threads命令~,应该有一个线程被标记为#,这表明线程有异常。如果看不到,则可能是活动线程,因为活动线程指示符 . 覆盖了异常指示符。在任何情况下,您都应该能够使用 ~#s(字面意思,不是用数字替换 #)来切换到异常线程。

堆栈 space 是否真的耗尽,应该可以使用 !teb 命令并查看堆栈基数和堆栈限制来弄清楚。然后将其与堆栈指针(ESP 寄存器)进行比较。