I’ve gotten some questions about how appdomains are handled at the ICorDebug level. Here’s some random trivia (this is kind of like the AppDomain version of the random-ICDThread trivia post I did earlier):
- Breakpoints: An ICorDebugBreakpoint is AppDomain specific. That means the debugger needs to do extra work to simulate a “process-wide” breakpoint; which really is just rebinding a breakpoint each time an appdomain loads a source-file. Both MDbg and VS do this work for you. (In MDbg’s case, an MDbgBreakpoint object has a collection of ICorDebugBreakpoints.)
- Threads: Threads can cross AppDomains (eg, call something on a marshal-by-ref object from another appdomain). Threads have a “current appdomain” (ICDThread::GetAppDomain) property.
- Identification: Appdomains have a unique AppDomain ID, which is unique throughout the lifetime of the process. This is retrieved by ICDAppDomain::GetId(). AppDomains also can have a “friendly name” (AppDomain.FriendlyName), which is retrieved by ICDAppDomain::GetName(). There is a NameChange debug event when the friendly name is changed.
Unlike modules, appdomain names are dynamic and can be assigned at runtime. For example, AppDomain Id 2 doesn’t mean much expect whatever appdomain was the 2nd to be created. And friendly names can be random and generated at runtime. This makes it difficult to serialize app-domain specific breakpoint locations across debug sessions.
- Load/Unload events: There are managed debug events for when an AppDomain is loaded an when it exits. The default domain (the first one created) may or may not send an unload event at process shutdown. Shufficiently rude process termination (such as exiting via task-manager) may mean you don’t get some unload events, although you’ll always get the ExitProcess event.
- Partial-Process-debugging: Contrary to what the ICorDebugAPI may imply with things like ICorDebugAppDomain::IsAttached, managed debugging is a process-wide operation. You can’t debug just a single appdomain in isolation from all the other appdomains. This would have been very nice, but there are some challenges that make it very difficult for this to be done in a general way. More on this later…
One example of this in action: so you can set a breakpoint in one appdomain, and then any thread in the process that hits the code in that appdomain will hit that breakpoint. However, the entire process (including all the other appdomains) will still be stopped to dispatch the breakpoint event.
- Transparent proxies/ Marshalling: Warning: ICD does not do a good job of debugging support for Transparent Proxies or Context-Bound objects.
A lot of these implications can be inferred by the parent-child relationships in the ICorDebug interfaces.
This talks about what debugging AppDomains look at the platform level (ICorDebug). There’s another great discussion to be had about what sort of UI an end-user debugger (like VS) should have to best support debugging multiple-appdomain applications.