AppDomains with true fault tolerance??

Hi.

I am working on a server application in C# that allows the users to add their clients or plug-ins.  I provide an API for what functions the client has to implement and load the client object (and assembly) into a new application domain.  The client objects are either MarshalByRefObj or are serializable as needed.  My server will then call one or two functions on the client object to set it up and let it run (perhaps in a separate thread, or using a GUI, created by the client).  

My question is: how do I get true fault tolerance?  

Right now, for the sake of testing, I am loading in a client object that does a division by zero after loading up a GUI, and it crashes my entire server!  Perhaps I was mistaken, but I thought the application domains are supposed to provide isolation and fault tolerance.  Is there a way to add a layer of fault tolerance, in case the user's plugin/client does something stupid?  I know there are security permissions, but from what I can tell they only stop things like file and network access, not isolate the exceptions from the server.

Do I have to go to seperate processes and use remoting to talk to my server?  I'd really rather not, unless it is the only way.

I really appreciate any assistance!  
Thanks in advance.
SharonMillerAsked:
Who is Participating?
 
AvonWyssConnect With a Mentor Commented:
When you are running a GUI, .NET has another handler of its own for exceptions in the GUI. See System.Windows.Forms.Application.ThreadException for details.
0
 
AvonWyssCommented:
You should be able to catch exceptions in the code by creating a small "loader" which you run in the new AppDomain which then loads and executes the plugin methods. The loader must provide proper exception handing; this should solve your problem.
0
 
SharonMillerAuthor Commented:
I see what you are saying, but I'm not sure that will always work in my case.  For example, with just one method call from the server, say Run( ), a client may start up several threads to do some processing and may run for the entire lifetime of the server application.  The Run() method would return immediately, successfully, but at some later time the client threads may do something unexpected.  With this asynchronous, multi-threaded operation, I don't think a try/catch around the initial method call is going to do it, unless I misunderstood what you are suggesting.

Thanks.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
ptmcompCommented:
Have a look at NUnit (www.nunit.org) they are starting the code to test in a new AppDomain. But even there are still problems sometimes. Namely under Framwork 1.0 there are problems unloading a domain.
0
 
AvonWyssConnect With a Mentor Commented:
I see your point, Sharon. In that case, assign an UnhandledExceptionEventhandler to the AppDomain.UnhandledException event.
0
 
SharonMillerAuthor Commented:
AvonWyss, I think we are getting close.  I've looked at that event handler too.  In some basic test cases it seems to do the trick.  However, if my client starts up its own gui, by using the call Application.Run(new ClientForm()), and the gui throws the exception, my UnhandledExceptionEventHandler doesn't seem to catch the error.   Is this a known "feature" of running a gui?  Is there another way to run a gui without using this call?  

ptmcomp, Is there sample code at nunit.org that shows how they isolate the code into the AppDomains.  I didn't see any relevant links, just samples on how to use the NUnit tool.  But, perhaps I didn't look hard enough :)

0
 
SharonMillerAuthor Commented:
Thanks AvonWyss!

I've played around with these two exception handlers, and try/catches, and as long as I put them in the right places, I think it will work.  

Just for anyone's future reference, I thought I'd add some points I've noticed (which may be obvious to others :)

The Application.ThreadException handler must be set up and the event caught in the newly created domain if the client object is serializable and hence executing in the new domain.  Else, the handler must be set up in the original server domain if the client object was marshalled by ref, and hence is executed like it exists in the server domain.

The AppDomain.UnhandledException handler must be set up on the original server AppDomain, can catch exceptions generated by additional client threads (from a client object that is serialized or marshalbyref), but will not catch GUI-generated exceptions from the client object.

And finally, a try/catch around a call to the new app domain must be used to catch any unhandled exceptions that originated in the client AppDomain, but did not involve any additional threads or a GUI.
0
 
AvonWyssCommented:
Thanks for the feedback, SharonMiller!

The handler needing to be MarshalByRef or serializable is due to the fact that AppDomains are context boundaries. I forgot to mention that, but apparently you didn't have to much problems with it. Still, note that apparantly, uncatchable exceptions (like execution engine and out of memory errors) will still stop the whole process. This is by design and can only be prevented by using a separate process.
0
All Courses

From novice to tech pro — start learning today.