为什么子AppDomain中的StackOverflowException会终止父AppDomain?

时间:2011-02-22 12:38:53

标签: .net appdomain stack-overflow

我的印象是AppDomains彼此隔离。似乎在StackOverException的情况下,情况并非如此。

为了演示这个问题,我创建了一个简单的控制台应用程序,其唯一目的是生成一个新的AppDomain,我在其中加载一个非常简单的程序集并调用其中一个方法。此方法恰好抛出StackOverflowException。这导致我的控制台应用程序毫不客气地终止。

我希望的行为是“子”AppDomain在这样的异常上崩溃和刻录,但是保持我的控制台应用程序在“父”AppDomain中运行,没有受到损坏。

这可能吗?

更新:这是一些代码。两个异常处理程序都没有被命中。

    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            // create app domain
            var domain = AppDomain.CreateDomain("MyDomain");

            // create a component
            var component = (MyComponent)domain.CreateInstanceAndUnwrap(
                "AppDomainMonitor.Component", 
                typeof(MyComponent).FullName);

            // create a thread from a method on this component
            var thread = new Thread(component.CauseStackOverflow);

            // start the thread
            thread.Start();

            Console.ReadKey();
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            // never hit
        }
    }

    public class MyComponent : MarshalByRefObject
    {
        public void CauseStackOverflow()
        {
            try
            {
                Infinite();
            }
            catch (Exception ex)
            {
                // never hit
            }
        }


        void Infinite()
        {
            Infinite();
        }
    }

2 个答案:

答案 0 :(得分:8)

AppDomains之间仅隔离了托管内存。如果一个线程在任何AppDomain中抛出异常,这将导致整个应用程序崩溃。

我认为最好的解决方案是确保在每个线程(或线程池工作项)上正确处理所有异常。

然而,有一个hack包括在App.Config文件中应用此配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="1"/>
  </runtime>
</configuration>

自.Net 2.0以来,未处理的异常会导致进程崩溃,但您可以使用此技巧恢复旧策略。

我会谨慎地使用它,因为通常最好让进程崩溃而不是静默失败。您可以在AppDomain.UnhandledException中添加跟踪,以便在发生未处理的异常时得到通知并正确处理它们。

修改

你对StackOveflowException是正确的,因为.Net 2.0这个异常不能被用户代码处理。 (参见this page in msdn的备注部分)。

有一种方法可以通过创建自定义CLR主机来覆盖它,但这似乎是一件疯狂的事情。我想你将不得不忍受它,或者你可以创建子进程而不是AppDomain,如果你真的需要这种容错。

答案 1 :(得分:1)

我认为问题是你在主AppDomain中调用导致异常的方法,也就是你在主AppDomain中调用一些方法,这个方法从子AppDomain调用问题方法。子AppDomain中的异常会增加,但它会在调用堆栈中向上传播到您的调用AppDomain(主AppDomain)。尝试完全从子AppDomain调用此方法。例如,在子AppDomain中生成一个线程,这样该线程就应该调用问题方法。