public void Emit(Compilation mainCompilation, IEnumerable <ResourceDescription> manifestResources) { var diagnostics = DiagnosticBag.GetInstance(); var dependencies = new List <ModuleData>(); testData.Methods.Clear(); ImmutableArray <byte> mainImage, mainPdb; bool succeeded = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, testData, out mainImage, out mainPdb); this.lazyDiagnostics = diagnostics.ToReadOnlyAndFree(); if (succeeded) { this.mainModule = new ModuleData(mainCompilation.Assembly.Identity, mainCompilation.Options.OutputKind, mainImage, mainPdb, inMemoryModule: true); this.allModuleData = dependencies; this.allModuleData.Insert(0, mainModule); CreateAssemblyManager(dependencies, mainModule); } else { string dumpDir; RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir); // This method MUST throw if compilation did not succeed. If compilation succeeded and there were errors, that is bad. // Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure. throw new EmitException(this.lazyDiagnostics, dumpDir); // ToArray for serializability. } }
internal Assembly GetOrLoad(ModuleData moduleData, bool reflectionOnly) { var cache = reflectionOnly ? _reflectionOnlyAssemblyCache : _assemblyCache; lock (s_guard) { Assembly assembly; if (cache.TryGetValue(moduleData.Mvid, out assembly)) { return(assembly); } var loadedAssembly = RuntimeAssemblyManager.LoadAsAssembly(moduleData.SimpleName, moduleData.Image, reflectionOnly); // Validate the loaded assembly matches the value that we now have in the cache. if (!cache.TryGetValue(moduleData.Mvid, out assembly)) { throw new Exception("Explicit assembly load didn't update the proper cache"); } if (loadedAssembly != assembly) { throw new Exception("Cache entry doesn't match result of load"); } return(assembly); } }
void IDisposable.Dispose() { if (disposed) { return; } if (domain == null) { if (assemblyManager != null) { assemblyManager.Dispose(); assemblyManager = null; } } else { Debug.Assert(assemblyManager != null); assemblyManager.Dispose(); if (IsSafeToUnloadDomain) { AppDomain.Unload(domain); } assemblyManager = null; domain = null; } disposed = true; }
void IDisposable.Dispose() { if (_disposed) { return; } if (_domain == null) { if (_assemblyManager != null) { _assemblyManager.Dispose(); _assemblyManager = null; } } else { Debug.Assert(_assemblyManager != null); _assemblyManager.Dispose(); if (IsSafeToUnloadDomain) { AppDomain.Unload(_domain); } _assemblyManager = null; _domain = null; } _disposed = true; }
private void CreateAssemblyManager(IEnumerable <ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (_additionalDependencies != null) { allModules = allModules.Concat(_additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); if (conflict != null && !CLRHelpers.IsRunningOnMono()) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; AppDomain appDomain = null; RuntimeAssemblyManager manager; try { appDomain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, AppDomain.CurrentDomain.BaseDirectory, null, false); manager = (RuntimeAssemblyManager)appDomain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } catch { if (appDomain != null) { AppDomain.Unload(appDomain); } throw; } _domain = appDomain; _assemblyManager = manager; } else { _assemblyManager = new RuntimeAssemblyManager(); } _assemblyManager.AddModuleData(allModules); if (mainModule != null) { _assemblyManager.AddMainModuleMvid(mainModule.Mvid); } }
private void CreateAssemblyManager(IEnumerable<ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (additionalDependencies != null) { allModules = allModules.Concat(additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); if (conflict != null) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; AppDomain appDomain = null; RuntimeAssemblyManager manager; try { appDomain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, AppDomain.CurrentDomain.BaseDirectory, null, false); manager = (RuntimeAssemblyManager)appDomain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } catch { if (appDomain != null) { AppDomain.Unload(appDomain); } throw; } this.domain = appDomain; this.assemblyManager = manager; } else { this.assemblyManager = new RuntimeAssemblyManager(); } this.assemblyManager.AddModuleData(allModules); if (mainModule != null) { this.assemblyManager.AddMainModuleMvid(mainModule.Mvid); } }
internal string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true) { peVerifyRequested = true; if (assemblyManager == null) { assemblyManager = CreateAssemblyManager(new ModuleData[0], null); } return(assemblyManager.PeVerifyModules(modulesToVerify, throwOnError)); }
public void Emit( Compilation mainCompilation, IEnumerable <ResourceDescription> manifestResources, bool usePdbForDebugging = false) { _testData.Methods.Clear(); var diagnostics = DiagnosticBag.GetInstance(); var dependencies = new List <ModuleData>(); var mainOutput = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, _testData); _emitData = new EmitData(); _emitData.Diagnostics = diagnostics.ToReadOnlyAndFree(); if (mainOutput.HasValue) { var mainImage = mainOutput.Value.Assembly; var mainPdb = mainOutput.Value.Pdb; _emitData.MainModule = new ModuleData( mainCompilation.Assembly.Identity, mainCompilation.Options.OutputKind, mainImage, pdb: usePdbForDebugging ? mainPdb : default(ImmutableArray <byte>), inMemoryModule: true); _emitData.MainModulePdb = mainPdb; _emitData.AllModuleData = dependencies; // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. _emitData.AllModuleData.Insert(0, _emitData.MainModule); _emitData.RuntimeData = CreateAndInitializeRuntimeData(dependencies, _emitData.MainModule.Id); } else { string dumpDir; RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir); // This method MUST throw if compilation did not succeed. If compilation succeeded and there were errors, that is bad. // Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure. throw new EmitException(_emitData.Diagnostics, dumpDir); } }
private RuntimeAssemblyManager CreateAssemblyManager(IEnumerable <ModuleData> compilationDependencies, ModuleData mainModule) { var allModules = compilationDependencies; if (additionalDependencies != null) { allModules = allModules.Concat(additionalDependencies); } // We need to add the main module so that it gets checked against already loaded assembly names. // If an assembly is loaded directly via PEVerify(image) another assembly of the same full name // can't be loaded as a dependency (via Assembly.ReflectionOnlyLoad) in the same domain. if (mainModule != null) { allModules = allModules.Concat(new[] { mainModule }); } allModules = allModules.ToArray(); string conflict = DetectNameCollision(allModules); RuntimeAssemblyManager manager; if (conflict != null) { Type appDomainProxyType = typeof(RuntimeAssemblyManager); Assembly thisAssembly = appDomainProxyType.Assembly; this.domain = AppDomain.CreateDomain("HostedRuntimeEnvironment", null, Environment.CurrentDirectory, null, false); manager = (RuntimeAssemblyManager)domain.CreateInstanceAndUnwrap(thisAssembly.FullName, appDomainProxyType.FullName); } else { manager = new RuntimeAssemblyManager(); } manager.AddModuleData(allModules); if (mainModule != null) { manager.AddMainModuleMvid(mainModule.Mvid); } return(manager); }
void IDisposable.Dispose() { if (disposed) { return; } if (domain == null) { if (assemblyManager != null) { assemblyManager.Dispose(); assemblyManager = null; } } else { // KevinH - I'm adding this for debugging...we seem to be getting to AppDomain.Unload when we shouldn't // (causing intermittant failures on the build machine). We should never be creating a separate // AppDomain without its own assemblyManager. if (assemblyManager == null) { throw new InvalidOperationException("assemblyManager should never be null if a remote domain was created"); } else { assemblyManager.Dispose(); if (IsSafeToUnloadDomain) { AppDomain.Unload(domain); } assemblyManager = null; } domain = null; } disposed = true; }
internal RuntimeData(RuntimeAssemblyManager manager, AppDomain appDomain) { Manager = manager; AppDomain = appDomain; }
public AssemblyLoader(RuntimeAssemblyManager manager) { _manager = manager; }
public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, bool emitPdb) { var diagnostics = DiagnosticBag.GetInstance(); var dependencies = new List<ModuleData>(); testData.Methods.Clear(); ImmutableArray<byte> mainImage, mainPdb; bool succeeded = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, emitPdb, testData, out mainImage, out mainPdb); this.lazyDiagnostics = diagnostics.ToReadOnlyAndFree(); if (succeeded) { this.mainModule = new ModuleData(mainCompilation.Assembly.Identity, mainCompilation.Options.OutputKind, mainImage, mainPdb, inMemoryModule: true); this.allModuleData = dependencies; this.allModuleData.Insert(0, mainModule); this.assemblyManager = CreateAssemblyManager(dependencies, mainModule); } else { string dumpDir; RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir); // This method MUST throw if compilation did not succeed. If compilation succeeded and there were errors, that is bad. // Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure. throw new EmitException(this.lazyDiagnostics, dumpDir); // ToArray for serializability. } }
internal string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true) { peVerifyRequested = true; if (assemblyManager == null) { assemblyManager = CreateAssemblyManager(new ModuleData[0], null); } return assemblyManager.PeVerifyModules(modulesToVerify, throwOnError); }