开发者

Why does a StackOverflowException in a child AppDomain terminate the parent AppDomain?

I was under the impression that AppDomains are isolated from each other. It seems that in the case of a StackOverException, this isn't the case.

To demonstrate the issue, I created a simple console application whose only purpose is to spawn a new AppDomain, into which I load a very simple assembly and call one of its methods. This method happens to throw 开发者_如何学Ca StackOverflowException. This causes my console application to terminate unceremoniously.

My desired behavior is for the "child" AppDomain to crash and burn on such an exception, but leave my console application, running in the "parent" AppDomain, unscathed.

Is this possible?

UPDATE: here is some code. Neither of the exception handlers are hit.

    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();
        }
    }


Only the managed memory is isolated between AppDomains. If a thread throws an exception in any AppDomain, this will cause the whole application to crash.

I think the best solution is to ensure that all exceptions are properly handled on every thread (or thread pool work items).

There is however a hack which consist of applying this configuration in the App.Config file:

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

Unhandled exceptions are crashing the process since .Net 2.0, but you can revert to the old policy using this trick.

I would use this cautiously tough as it's often best to let processes crash instead of failing silently. You can add traces in AppDomain.UnhandledException to be notified when unhandled exception occurs and handle them appropriately.

EDIT

You are right about StackOveflowException, since .Net 2.0 this exception cannot be handled by user code. (See the Remarks section of this page in msdn).

There is a way to override this by creating a custom CLR host, but this seems like a crazy thing to do. I guess you'll have to live with it or you can create child process instead of AppDomain if you really need this kind of fault tolerance.


I suppose the problem is that you call method causing an exception from within your main AppDomain, that is you call some method in main AppDomain, this method calls problem method from child AppDomain. Exception rises in child AppDomain, but it is propagated up the call stack to your calling AppDomain (main AppDomain). Try to call this method from child AppDomain entirely. For example, spawn a thread in child AppDomain, so that this thread should call problem method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜