diff --git a/Mono.Debugging.Soft/SoftDebuggerSession.cs b/Mono.Debugging.Soft/SoftDebuggerSession.cs index 4c4a9a62a..5ef9b6266 100644 --- a/Mono.Debugging.Soft/SoftDebuggerSession.cs +++ b/Mono.Debugging.Soft/SoftDebuggerSession.cs @@ -52,6 +52,7 @@ public class SoftDebuggerSession : DebuggerSession { readonly Dictionary, MethodMirror[]> overloadResolveCache = new Dictionary, MethodMirror[]> (); readonly Dictionary> source_to_type = new Dictionary> (PathComparer); + readonly Dictionary domainAssemblies = new Dictionary(); readonly Dictionary activeExceptionsByThread = new Dictionary (); readonly Dictionary breakpoints = new Dictionary (); readonly Dictionary symbolFiles = new Dictionary (); @@ -417,8 +418,8 @@ void ConnectionStarted (VirtualMachine machine) ConnectOutput (machine.StandardError, true); HideConnectionDialog (); - - machine.EnableEvents (EventType.AssemblyLoad, EventType.ThreadStart, EventType.ThreadDeath, + + machine.EnableEvents (EventType.AppDomainCreate, EventType.AppDomainUnload, EventType.AssemblyLoad, EventType.ThreadStart, EventType.ThreadDeath, EventType.AssemblyUnload, EventType.UserBreak, EventType.UserLog); try { unhandledExceptionRequest = machine.CreateExceptionRequest (null, false, true); @@ -1455,6 +1456,12 @@ void HandleEventSet (EventSet es) } switch (type) { + case EventType.AppDomainCreate: + HandleAppDomainCreateEvents (Array.ConvertAll(es.Events, item => (AppDomainCreateEvent)item)); + break; + case EventType.AppDomainUnload: + HandleAppDomainUnloadEvents (Array.ConvertAll(es.Events, item => (AppDomainUnloadEvent)item)); + break; case EventType.AssemblyLoad: HandleAssemblyLoadEvents (Array.ConvertAll (es.Events, item => (AssemblyLoadEvent)item)); break; @@ -1789,6 +1796,59 @@ void HandleBreakEventSet (Event[] es, bool dequeuing) } } + void RemoveUnloadedAssemblyTypes(AssemblyMirror asm) + { + // Remove affected types from the loaded types list + var affectedTypes = new List(from pair in types + where PathComparer.Equals(pair.Value.Assembly.Location, asm.Location) + select pair.Key); + + foreach (string typeName in affectedTypes) + { + TypeMirror tm; + + if (types.TryGetValue(typeName, out tm)) + { + if (tm.IsNested) + aliases.Remove(NestedTypeNameToAlias(typeName)); + + types.Remove(typeName); + } + } + + foreach (var pair in source_to_type) + { + pair.Value.RemoveAll(m => PathComparer.Equals(m.Assembly.Location, asm.Location)); + } + } + + void HandleAppDomainCreateEvents(AppDomainCreateEvent[] events) + { + var domain = events[0].Domain; + if (events.Length > 1) + throw new InvalidOperationException("Simultaneous AppDomainCreateEvent for multiple domains"); + + if(!domainAssemblies.ContainsKey(domain)) + domainAssemblies[domain] = null; + } + + void HandleAppDomainUnloadEvents(AppDomainUnloadEvent[] events) + { + var domain = events[0].Domain; + if (events.Length > 1) + throw new InvalidOperationException("Simultaneous AppDomainUnloadEvent for multiple domains"); + + if (!domainAssemblies.ContainsKey(domain)) + return; + + var assemblies = domainAssemblies[domain]; + + foreach (var asm in assemblies) + RemoveUnloadedAssemblyTypes(asm); + + domainAssemblies.Remove(domain); + } + void HandleAssemblyLoadEvents (AssemblyLoadEvent[] events) { var asm = events [0].Assembly; @@ -1802,6 +1862,11 @@ void HandleAssemblyLoadEvents (AssemblyLoadEvent[] events) string flagExt = isExternal ? " [External]" : ""; OnDebuggerOutput (false, string.Format ("Loaded assembly: {0}{1}\n", asm.Location, flagExt)); + + // Update loaded assemblies for each domain + var domains = new List(domainAssemblies.Keys); + foreach (var domain in domains) + domainAssemblies[domain] = domain.GetAssemblies(); } void HandleAssemblyUnloadEvents (AssemblyUnloadEvent[] events) @@ -1829,25 +1894,7 @@ void HandleAssemblyUnloadEvents (AssemblyUnloadEvent[] events) pending_bes.Add (breakpoint.Value); } - // Remove affected types from the loaded types list - var affectedTypes = new List (from pair in types - where PathComparer.Equals (pair.Value.Assembly.Location, asm.Location) - select pair.Key); - - foreach (string typeName in affectedTypes) { - TypeMirror tm; - - if (types.TryGetValue (typeName, out tm)) { - if (tm.IsNested) - aliases.Remove (NestedTypeNameToAlias (typeName)); - - types.Remove (typeName); - } - } - - foreach (var pair in source_to_type) { - pair.Value.RemoveAll (m => PathComparer.Equals (m.Assembly.Location, asm.Location)); - } + RemoveUnloadedAssemblyTypes(asm); } OnDebuggerOutput (false, string.Format ("Unloaded assembly: {0}\n", asm.Location)); }