Application Domain isolation - c#

"The isolation provided by application domains has the following benefits:
Faults in one application cannot affect other applications. Because type-safe code cannot cause memory faults, using application domains ensures that code running in one domain cannot affect other applications in the process."##
http://msdn.microsoft.com/en-us/library/2bh4z9hs.aspx
The above words was got from The MSDN,
My questions are,
1, The "Faults" in the sentence refer to the exception ,or something else?
2, what is The "Faults in one application cannot affect other applications" means?,
Does it means if there throw an exception in one Application Domain ,that exception will not crash other Application Domains, right?
Can you give me an example ?

The article talks about memory isolation. Managed code can't arbitraty modify memory (without unsafe) unlike C/C++ thus managed code running in one AppDomain will not corrupt memory in other AppDomain. I.e. buffer overflow kind of errors are prevented by managed runtime, while easy to achieve in C/C++ like int arr[4]; arr[-1]=2;.
Exceptions are not scoped to AppDomain (or rather behave similar with/without AppDomains) - most exceptions will only impact code that called method that throws exception, some (i.e. StackOverflow) by default will terminate the process. If normal exception is unhandled it normally will cause process termination. Exceptions are free to cross AppDomain boundaries if code on the stack bekongs to multiple AppDomains.

Related

Is there any way to print any extended information on StackOverflowException?

One of my clients reported that the software I develop terminates unexpectedly. In app log, the only text available is Process is terminated due to StackOverflowException. There is no more information which would help me diagnose and fix it.
Is there any way to get the location where the exception was thrown? VS breaks on StackOverflowException, but is there any feasible method of diagnosing it without running the application in the debugger (or looking for it in all methods which contain recursion)?
You cannot normally execute any code after a stack overflow, it's one of the rare uncatchable fatal exceptions, so you cannot simply catch it to log any extended details.
The only way you could work around that is by tracking the exceptions from outside of the code that has a stack overflow. You would need to create a native code application to hosts the CLR. If you do that, you can specify that StackOverflowException is not 100% fatal. This is briefly mentioned on the StackOverflowException MSDN page:
If your app hosts the common language runtime (CLR), it can specify that the CLR should unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface.
But even that would still mean that a simple try...catch is not sufficient to actually catch the exception. You would have to make sure that the exception handling is not done from the app domain that has a stack overflow. It might be done from a different app domain, or it might be done from unmanaged code.

Are CER needed to merely protect shared managed states within an AppDomain?

I do have an operation that must be reliably performed as a whole or not be performed at all.
The goal is only to preserve the consistency of some in-memory managed shared states.
Those states are contained within an application domain. They are not visible outside of this domain.
I therefore do not have to react when the domain or the process are teared down.
I am writing a class library and the user may call my code from anywhere. However my code does not call any user code, not even virtual methods.
The CLR may be hosted.
To my understanding I do not need constrained execution regions (CER) since:
CER are only needed against the infamous OutOfMemoryException, ThreadAbortException and StackOverflowException.
My code does not make any allocation, so I do not care about OutOfMemory (anyway allocations must not be done within a CER).
If a stack overflow occurs the process will be teared down anyway (or the domain in some hosted scenarios).
Thread aborts are already delayed until the end of a finally block and my code is already within one.
Am I correct on those points? Do you see other reasons why I should need CER?
I finally found at least one reason why a CER is still needed: even if my code does not do any allocation, the JIT compiler may have to allocate memory on the first execution.
Therefore putting a CER is required to force the runtime to JIT everything beforehand and prevent a possible OOM.

How to deal with exceptions on separate threads in an external dll?

I'm loading in a dll that spawns a few threads within itself. Every now and then the program crashes with an unhandled exception. I can't wrap all my library calls in try/catch statements because the exceptions are being thrown on separate threads, and I don't have access to the library's source to debug/fix the bad error handling. I'd like the program to keep doing other things when these exceptions happen, is there a graceful way to handle these exceptions? Or is the only thing I can do to do a global catch all exceptions method?
If you load the DLL into a separate appdomain, you should be able to isolate exceptions generated with a AppDomain.UnhandledException, but, be aware that this is not fool proof and there are certain situations where it will still take your process out too and there is nothing you can do about it (stack overflow, out of memory etc).
The best you can do in that case is load them in a separate process completely with some kind of dll communication harness and using some form of remoting to talk to that process.
I would recommend to implement a separate process (EXE) which your application launches and which in turn loads the DLL.
This allows you to kill/restart the process whenever need be...
I see several options on how to communicate - for example:
you could use COM (if you implement it as an out-of-process COM server)
you could use shared memory (very high performance, see this for a walkthrough and this for a .NET 2 wrapper)
IF the method must be compatible with several Windows versions THEN I would refrain from using anything "networky" for the IPC (since some come with a desktop firewall).

Corrupted state exceptions (CSE) across AppDomain

For some background info, .NET 4.0 no longer catches CSEs by default: http://msdn.microsoft.com/en-us/magazine/dd419661.aspx
I'm working on an app that executes code in a new AppDomain. If that code throws a CSE, the exception bubbles up to the main code if it's not handled. My question is, can I safely assume that a CSE on the second AppDomain won't corrupt the state in the main AppDomain, and thus exit the second AppDomain and continue running the main AppDomain?
In the context of a corrupted state exception, in general, you cannot assume anything to be true anymore. The point of these exceptions is that something has happened, usually due to buggy unmanaged code, that has violated some core assumption that Windows or the CLR makes about the structure of memory. That means that, in theory, the very structures that the CLR uses to track which app domains exist in memory could be corrupted. The kinds of things that cause CSEs are generally indicative that things have gone catastrophically wrong.
Having said all that, off-the-record, in some cases, you may be able to make a determination that it is safe to continue from a particular exception. An EXCEPTION_STACK_OVERFLOW, for example, is probably recoverable, and an EXCEPTION_ACCESS_VIOLATION usually indicates that Windows caught a potential bug before it had a chance to screw anything up. It's up to you if you're willing to risk it, depending on how much you know about the code that is throwing the CSEs in the first place.

What are app domains used for?

I understand roughly what an AppDomain is, however I don't fully understand the uses for an AppDomain.
I'm involved in a large server based C# / C++ application and I'm wondering how using AppDomains could improve stability / security / performance.
In particular:
I understand that a fault or fatal exception in one domain does not affect other app domains running in the same process - Does this also hold true for unmanaged / C++ exceptions, possibly even heap corruption or other memory issues.
How does inter-AppDomain communication work?
How is using AppDomains different from simply spawning many processes?
The basic use case for an AppDomain is in an environment that is hosting 3rd party code, so it will be necessary not just to load assemblies dynamically but also unload them.
There is no way to unload an assembly individually. So you have to create a separate AppDomain to house anything that might need to be unloaded. You can then trash and rebuild the whole AppDomain when necessary.
By the way, native code corrupting the heap cannot be protected against by any feature of the CLR. Ultimately the CLR is implemented natively and shares the same address space. So native code in the process can scribble all over the internals of the CLR! The only way to isolate badly behaved (i.e. most) native code is actual process isolation at the OS level. Launch mutiple .exe processes and have them communicate via some IPC mechanism.
I highly recommend CLR Via C# by Jeffrey Richter. In particular chapter 21 goes into good detail regarding the purpose and uses of AppDomains.
In answer to your points/question:
AppDomains will not protect your application from rogue unmanaged code. If this is an issue you will most likely need to use full process isolation provided by the OS.
Communication between AppDomains is performed using .NET remoting to enforce isolation. This can be via marshal by reference or marshal by value semantics, with a trade off between performance and flexibility.
AppDomains are a lightweight way of achieving process like isolation within managed code. AppDomains are considered lightweight because you can create multiple AppDomains within a single process and so they avoid the resource and performance overhead multiple OS processes. Also, a single thread can execute code in one AppDomain and then in another AppDomain as Windows knows nothing about AppDomains (see this by using using System.AppDomain.CurrentDomain)
Actually, it is not true that a critical fail in one AppDomain can't impact others. In the case of bad things, the best bet it to tear down the process. There are a few examples, but to be honest I haven't memorised them - I simply took a mental note "bad things = tear down process (check)"
Benefits of AppDomain:
you can unload an AppDomain; I use this for a system that compiles itself (meta-programming) based on data from the database - it can spin up an appdomain to host the new dll for a while, and then swap it safely when new data is available (and built)
comms between AppDomains are relatively cheap. IMO this is the only time I am happy to use remoting (although you still need to be really careful about the objects on the boundary to avoid bleeding references between them, causing "fusion" to load extra dlls into the primary AppDomain, causing a leak) - it is really easy too - just CreateInstanceAndUnwrap (or is it CreateInstanceFromAndUnwrap?).
vs spawing an extra process - you could go either way; but you don't need another exe for AppDomain work, and it is much easier to set up any comms that you need
I'm not claiming to be an expert on AppDomains, so my answer will not be all-encompassing. Perhaps I should start off by linking to a great introduction by a guy who does come off as somewhat an expert, and what does seem like covering all aspects of AppDomain usage.
My own main encounter with AppDomains has been in the security field. There, the greatest advantage I've found has been the ability to have a master domain run in high trust spawning several child domains with restricted permissions. By restricting permissions in high trust, without the use of app domains, the restricted processes would still have the permission to elevate their own privileges.
App Domain segregation strategy for running completely independent code modules, in order to address memory sharing and stability concerns, is more of an illusion than a reality.

Categories

Resources