From a957ab18a332d284b086aee622c8a0f05014e697 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Wed, 24 May 2017 11:18:36 -0400 Subject: [PATCH] [tests] Regression test for #56694 When an AssemblyLoad event fires in a domain, a System.Reflection.Assembly object is created in that domain for the assembly being loaded. The bug left this object alive after the domain was unloaded, which lead to a GC crash. --- mono/tests/Makefile.am | 1 + mono/tests/appdomain-unload-asmload.cs | 57 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 mono/tests/appdomain-unload-asmload.cs diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 58b826ef15a..f4182ec0e34 100755 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -463,6 +463,7 @@ TESTS_CS_SRC= \ assemblyresolve_event2.2.cs \ appdomain-unload-callback.cs \ appdomain-unload-doesnot-raise-pending-events.cs \ + appdomain-unload-asmload.cs \ unload-appdomain-on-shutdown.cs \ bug-47295.cs \ loader.cs \ diff --git a/mono/tests/appdomain-unload-asmload.cs b/mono/tests/appdomain-unload-asmload.cs new file mode 100644 index 00000000000..5f79890ca53 --- /dev/null +++ b/mono/tests/appdomain-unload-asmload.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading.Tasks; + +/* This is a regression test that checks that after an AssemblyLoad event fires + * in a domain, the domain can be unloaded. In bug # 56694, a + * System.Reflection.Assembly object from the unloaded domain was kept alive + * and crashed the GC. */ +namespace AppDomainUnloadAsmLoad +{ + class Program + { + static void Main(string[] args) + { + // Need some threads in play + new Program().Run().Wait(); + } + + private async Task Run() + { + var appDomain = AppDomain.CreateDomain("Test subdomain", null, AppDomain.CurrentDomain.SetupInformation); + try + { + var driver = (AppDomainTestDriver)appDomain.CreateInstanceAndUnwrap(typeof(AppDomainTestDriver).Assembly.FullName, + typeof(AppDomainTestDriver).FullName); + driver.Test(); + } + finally + { + AppDomain.Unload(appDomain); + } + } + } + + class AppDomainTestDriver : MarshalByRefObject + { + static AppDomainTestDriver() + { + // Needs a callback so that the runtime fires the + // AssembyLoad event for this domain and materializes a System.Reflection.Assembly + AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; + } + + private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) + { + } + + internal void Test() + { + /* this can be any class from any assembly that hasn't + * already been loaded into the test domain. + * System.Xml.dll is good because all the tests link + * against it, but it's not otherwise used by this + * domain. */ + var foo = default(System.Xml.XmlException); + } + } +} -- 2.25.1