.NET中的StackOverflowException> = 4.0 - 让其他线程有机会正常退出

时间:2014-07-24 08:33:17

标签: c# stack-overflow clr-hosting postmortem-debugging

有没有办法如何至少推迟托管应用程序的终止(几十毫秒)并设置一些共享标志,让其他线程有机会正常终止(SO线程本身不会明显执行任何进一步的操作)?我正在考虑使用JIT调试器或CLR托管 - 如果有人在此之前尝试过,我很好奇。

为什么我要做出错误的事情?:

没有太多细节 - 想象一下这个比喻 - 你在赌场投注轮盘赌,突然发现轮盘赌是不可靠的假货。所以你想立即离开赌场,但可能想先从桌面上下注。 遗憾的是,我无法利用单独的流程,因为性能要求非常严格。

尝试过但没有工作:

StackOverflowException的.NET行为(和MSDN上的矛盾信息)已在SO上多次讨论 - 以便快速总结:

HandleProcessCorruptedStateExceptionsAttribute(例如,在appdomain未处理的异常处理程序上)不起作用

ExecuteCodeWithGuaranteedCleanup不起作用

legacyUnhandledExceptionPolicy不起作用

可能很少有其他尝试如何处理StackOverflowExceptions - 但似乎很明显CLR终止了整个过程,如Hans Passant在this great answer中提到的那样。

考虑尝试:

  • JIT调试器 - 保留线程异常冻结,设置一些 共享标志(可能在固定位置)并解冻其他线程 时间很短。
  • CLR托管和设置未处理的例外政策
你还有其他想法吗?或者这两种方式的经验(成功/不成功)?

2 个答案:

答案 0 :(得分:4)

"假"对于你的赌场比喻来说,这不是一个正确的选择。发生了9级地震和赌场大楼以及轮盘赌桌,剩下的筹码和玩家消失在巨大的烟雾中。

在SOE之后运行代码的唯一镜头是远离该赌场,它必须在另一个进程中运行。 A"后卫"启动行为错误程序的进程,它可以使用Process.ExitCode来检测崩溃。它将是-1073741571(0xc00000fd)。进程状态消失了,您必须使用.NET进程间互操作方法之一(如WCF,命名管道,套接字,内存映射文件)来使防护进程知道需要的东西要做清理。这需要是交易性的,你无法推断崩溃发生的确切时间点,因为它可能在更新警卫时死亡。

请注意,这很少值得付出努力。因为SOE与日常流程中止无法区分。就像被任务管理器杀死一样。或者机器失去动力。或遭受地震的影响:)

答案 1 :(得分:3)

StackOverflowException是一个直接且关键的异常,运行时无法从中恢复 - 这就是为什么你无法捕获它,或从中恢复或其他任何东西。为了运行另一个方法(无论是清理方法还是其他方法),你必须能够为该方法创建一个堆栈框架,并且堆栈已经满了(这就是{{ 1}}意思是!)。你不能运行另一个方法,因为运行方法是导致异常的原因!

幸运的是,这种异常总是由程序结构引起的。您应该能够诊断并修复代码中的错误:当您获得异常时,您将在调用堆栈中看到有一个或多个方法的循环无限递归。您需要确定错误逻辑是什么并修复它,这比尝试修复不可修复的异常要容易得多。