none
AppDomains, Threading and UnhandledExceptions RRS feed

  • Question

  • Hello all,

    i am developing a application to experiment with genetic programming. As of now, the application is able to compile a model of source classes and wire events and methods according to the configuration stored in the model. Also, the application can mutate and rearrange the model in order to test alternative options.

    The idea is to compile and run mutations of the models in secondary appdomains, one for each model.
    This all works beautifull, the code gets compiled, the model is mutated the resulting population is executed, and none of the dynamic assemblies get loaded in the primary appdomain.

    There is a catch however, one which i have no solution for at the moment.
    When a user decides to write a piece of code, he can introduce code with possible faults. If such a piece of code executes on the main thread, the exception can be handled and processed safely. Not a problem there.
    However  when the user decides to introduce faulty code and execute it on a new thread (using classes available in the System.Threading namespace) the exception cannot be handled in any way.
    This means that the AppDomain.UnhandledException event gets raised in the primary AppDomain, and the managing application (the experiment) terminates.
    If i read the information regarding AppDomains and Threading correctly, this is by design of the CLR.
    My conclusion is that it is not possible to compile and run code on the fly, without introducing the risk of allowing for unhandled exceptions.

    Is there anyone that knows how to tackle this problem? 

    Many, many thanks in advance,

     
    Peter Vrenken - MCPD: Enterprise Applications Developer - Sigmax Mobile Solutions
    Wednesday, February 24, 2010 1:07 PM

All replies

  • This is my understanding as well that such exceptions are not recoverable.

    This is unfortunate, but I think Microsoft is being safe.  After all, the exception might have occured in unmanaged code.  AppDomains do not really provide any insulation from serious problems in unmanaged code such as memory access violations.  That being said, I don't totally agree with this.

    There are ways around it:
    1.  You can use <legacyUnhandledExceptionPolicy enabled="1"/>, if the word "legacy" doesn't bother you.
    2.  If your application is hosted, the host can use: ICLRPolicyManager::SetUnhandledExceptionPolicy

    FYI, here is an interesting MSDN article on unhandled exceptions:
    http://msdn.microsoft.com/en-us/magazine/cc793966.aspx

    > My conclusion is that it is not possible to compile and run code on the fly, without introducing the risk of allowing for unhandled exceptions.

    You could sandbox it with permissions that do not include the ability to create threads.

    How to: Run Partially Trusted Code in a Sandbox
    http://msdn.microsoft.com/en-us/library/bb763046.aspx

    Thursday, February 25, 2010 11:58 PM
  • Thanks for the response.

    I am researching CLR hosting right now, but am getting some weird results.

    Do you know if it is possible to host CLR's from within a running .NET application?

    Thanks in advance,
     
    Peter Vrenken - MCPD: Enterprise Applications Developer - Sigmax Mobile Solutions
    Saturday, February 27, 2010 11:22 PM
  • Hi Peter,

    I have a doubt. Pardon me, if it is too weird.

    You mentioned that you are trying to host the CLR, (I don't know whether it is possible to host a CLR from a running .NET app or not), if you succeeded on hosting the CLR from a .NET app, how are you going to kill a child thread.

    Say you have the parent thread, it spawns the child thread. In the original posting you mentioned you are doing a genetic programming and the the idea is to compile and run the mutation models. So there might be a chance that the child thread may spawn another thread and so on (correct me if I'm wrong). If my understanding is correct, in this scenario, say the exception is happened on depth of 5th level and bubbled to the main thread. In this place, you will have the main thread hold. In the worst case, the main thread may have thousands/millions of child threads (including the sub trees).

    I wonder how will you be able to find the child thread which throws the exception and how will you be able to kill that without killing the parent thread?

    Thanks and Regards,

    Vijay Pandurangan
    Monday, March 1, 2010 12:12 PM
  • Hello Vijay,

    thanks for the response.

    Hopefully the mutated code snippets will not have that many threads. In theory however, this could be possible.

    The idea is to have some kind of container that can be disposed of. If the compiled application does not work accordingly it will not get a decent fitness score and never survive to the next generation. This means that it isn't a big problem if the compiled code crashes, but i need to get rid of it somehow.
    Even if there is no way to know if a thread has terminated, i need to get rid of any executed code, including all created threads.

    It would be nice to know which thread failed (logging and such), but maintaining stability is a much greater issue.

    Does this make sense?

    Greetings,
    Peter Vrenken - MCPD: Enterprise Applications Developer - Sigmax Mobile Solutions
    Monday, March 1, 2010 6:33 PM
  • Hi Peter,

    It makes sense.

    If my understanding is correct, on any unhandled exceptions, you want to log the details about the exception and continue the execution of the experiment. But the application which throws the exception will not get the fitness score to survive to the the next generation. The goal is to save the parent app domain from the crash, so the experiment will continue with the other mutation models.

    Correct me if I'm wrong.

    Thanks and regards,



    Vijay Pandurangan
    Tuesday, March 2, 2010 3:28 AM
  • Yep.

    That is exactly what i am trying to do.

    The question is how...

    As far as i know i have the following options:

    1. Use CLR hosting somehow.
    2. Use AppDomains and catch unhandled exceptions.
          2.a. Use custom threading code that catches the exceptions.
          2.b. Configure the appdomains to somehow catch the exceptions
    3. Thought experiment: is it possible to use the Silverlight components anyhow? Silverlight can also be used to execute C# code.

    Just a quick dump of my thoughts in between a busy work schedule. :-)


    Peter Vrenken - MCPD: Enterprise Applications Developer - Sigmax Mobile Solutions
    Tuesday, March 2, 2010 9:47 AM
  • Hi Peter,

    Based on our previous discussion, I have come up with a workaround which may be helpful to you. 

        class Program
        {
            static void Main(string[] args)
            {
                var ar = new AutoResetEvent(false);
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
                Console.WriteLine("Creating Sub Domain");
                var ad = AppDomain.CreateDomain("SubDomain"); //Creating the Subdomain
                ad.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException); //Exception Handler for Sub Domain
                ad.DoCallBack(new CrossAppDomainDelegate(SampleClass.Invoke)); //Invoke the code to executed in sub domain
                //We need to wait on time basis
                //Since the threads thrown the exception are in suspended state
                //waiting without the time will end up in application running endless
                ar.WaitOne(2000);
                Console.WriteLine("Finished");
                Console.Read();
                //All the running threads are completed except the suspended one
                //Kill the main process and hence the sub threads will be killed
                //If you are using the thread pool, we don't need to kill the 
                //process as well as WaitHandle waiting with out timeout will also work, since in the ThreadPool
                //any thread which is suspended for more than 40 sec will be destroyed [http://msdn.microsoft.com/en-us/magazine/cc164139.aspx]
                System.Diagnostics.Process.GetCurrentProcess().Kill();
            }
            static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
                Console.WriteLine("Unhandled Exception Found in Main App Domain");
            }
            static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
                var cDomain = Thread.GetDomain();
                Console.WriteLine("Unhandled Exception Found in " + cDomain.FriendlyName);
                if (!cDomain.IsDefaultAppDomain())
                {
                    //Suspend the current thread for stopping the execution
                    Console.WriteLine("Suspending the SubDomain Thread. Domain Name: " + cDomain.FriendlyName);
                    //we don't require this exception handler any more
                    cDomain.UnhandledException -= new UnhandledExceptionEventHandler(UnhandledException);
                    Thread.CurrentThread.Suspend();
                }
            }
        }
        class SampleClass
        {
            public static void Invoke()
            {
                Thread tMethod = new Thread(MethodForException); //Thread launched from sub domain
                tMethod.Start();
            }
            private static void MethodForException()
            {
                throw new Exception(); //unhandled exception from the thread
            }
        }
    Its better to use ThreadPool (which will kill the thread after the 40 sec of suspension http://msdn.microsoft.com/en-us/magazine/cc164139.aspx) and hence no resource wastage. Let me know whether trying some thing as above let your experiment runs continuously.

    PS: In the above solution, I have suspended the thread which throws the exception. But I didn't unload the appdomain and it won't be helpful, since after the appdomain unloaded, the thread (which actually throws the exception) become orphan and handed over to the parent appdomain and resumes its execution which then results in unhandled exception and (if the thread doesn't resumes the execution in parent domain call) however after AppDomain.Unload() called, it will wait for 10 sec for the threads [http://blogs.msdn.com/nazimms/archive/2005/10/04/477067.aspx and see the community content in http://msdn.microsoft.com/en-us/library/system.appdomain.unload.aspx] in the appdomain to be get completed and if the threads are not smoothly completes the execution, it will terminate the thread by Thread.Abort() which will throws the thread abort exception (which is again unhandled) in main app domain which will crash the application.

    But leaving the appdomain with out unloading will consume a lot of resources. We have to unload the appdomains either by periodic check on all the appdomain (which are created) to unload if it has no alive threads or by timer base delegate by passing the sub appdomain object reference (before suspending the main thread of sub appdomain).

    Also correct me if any of my understanding is wrong.

    Thanks and regards,

    Vijay Pandurangan
    Wednesday, March 3, 2010 9:40 AM
  • Hi, Peter:
         How is your problem going on? Would you let us know your progress?
    Please mark the right answer at right time.
    Thanks,
    Sam
    Sunday, March 7, 2010 2:37 PM
  • Hello,

    i am quite busy for work atm (even on Sunday :-(), so i haven't got the chance to try it out. 

    I'll look into it as soon as possible!



     
    Peter Vrenken - MCPD: Enterprise Applications Developer - Sigmax Mobile Solutions
    Sunday, March 7, 2010 3:02 PM
  • Hi Peter,

    Do you find the solution about it?

    If you find, could you share some insight about it. Recently, I also run into this problem.

    Thanks

    Friday, July 2, 2010 11:10 PM
  • Hi Peter,

    I, too, have faced the problem of fault-isolation of application domains. I've blogged about a possible solution a while ago. You could check it out (code sample included):

    http://ikickandibite.blogspot.com/2010/04/appdomains-and-true-isolation.html


    Please mark this post as helpful if it is (or even mark it as an answer, if appropriate).
    Saturday, July 3, 2010 5:02 PM
  • The exception raised by the thread doesn't have to terminate you app. You can workaround it and do some logging too:

    Take a look:

    http://www.albahari.com/threading/#_Exception_Handling

     

    Good Luck

    Tuesday, October 5, 2010 4:03 PM