From b713b8a542c61becf8bf0cc35c7963d11f6da0c5 Mon Sep 17 00:00:00 2001 From: Johannes Gustafsson Date: Mon, 18 Sep 2017 14:04:14 +0200 Subject: [PATCH 1/2] Properly unload cleanup helper app domain after an isolated service is disposed. --- .../Compilation/CrossAppDomainCleanUp.cs | 2 +- .../RazorEngineCleanupTests.cs | 54 +++++++++++++++++++ .../Test.RazorEngine.Core.csproj | 11 ++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/source/RazorEngine.Core/Compilation/CrossAppDomainCleanUp.cs b/src/source/RazorEngine.Core/Compilation/CrossAppDomainCleanUp.cs index d906d711..9f5a1071 100644 --- a/src/source/RazorEngine.Core/Compilation/CrossAppDomainCleanUp.cs +++ b/src/source/RazorEngine.Core/Compilation/CrossAppDomainCleanUp.cs @@ -365,7 +365,7 @@ void domain_DomainUnload(object sender, EventArgs e) } } // We are not needed anymore. - //AppDomain.Unload(AppDomain.CurrentDomain); + AppDomain.Unload(AppDomain.CurrentDomain); }); t.IsBackground = false; t.Start(); diff --git a/src/test/Test.RazorEngine.Core/RazorEngineCleanupTests.cs b/src/test/Test.RazorEngine.Core/RazorEngineCleanupTests.cs index 7680b3e4..ee98f71c 100644 --- a/src/test/Test.RazorEngine.Core/RazorEngineCleanupTests.cs +++ b/src/test/Test.RazorEngine.Core/RazorEngineCleanupTests.cs @@ -7,8 +7,10 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Test.RazorEngine @@ -102,5 +104,57 @@ public void RazorEngineService_TestDisableTempFileLocking() data.DeleteAll(); Assert.IsFalse(Directory.Exists(folder)); } + + [Serializable] + public class TemplateModel + { + public string Name { get; set; } + } + + [Test] + public void RazorEngineService_CleanupDomainIsUnloaded() + { + Func CleanupDomainExists = () => + GetAppDomains() + .Any(x => x.FriendlyName.StartsWith("CleanupHelperDomain_")); + + Assert.False(CleanupDomainExists(), "Cleanup helper app domain should not exist before test is run."); + using (var service = IsolatedRazorEngineService.Create()) + { + service.AddTemplate("TestTemplate", + "Hello @Model.Name " + new String(Enumerable.Repeat('A', 100000).ToArray())); + service.Compile("TestTemplate", typeof(TemplateModel)); + + Assert.True(CleanupDomainExists(), "Cleanup helper app domain should exist after a template is compiled"); + } + + Thread.Sleep(300); + Assert.False(CleanupDomainExists(), "Cleanup helper app domain must be properly unloaded after service is disposed"); + } + + private static IList GetAppDomains() + { + IList _IList = new List(); + IntPtr enumHandle = IntPtr.Zero; + mscoree.ICorRuntimeHost host = new mscoree.CorRuntimeHost(); + try + { + host.EnumDomains(out enumHandle); + object domain = null; + while (true) + { + host.NextDomain(enumHandle, out domain); + if (domain == null) break; + AppDomain appDomain = (AppDomain)domain; + _IList.Add(appDomain); + } + return _IList; + } + finally + { + host.CloseEnum(enumHandle); + Marshal.ReleaseComObject(host); + } + } } } diff --git a/src/test/Test.RazorEngine.Core/Test.RazorEngine.Core.csproj b/src/test/Test.RazorEngine.Core/Test.RazorEngine.Core.csproj index 43310119..b434daab 100644 --- a/src/test/Test.RazorEngine.Core/Test.RazorEngine.Core.csproj +++ b/src/test/Test.RazorEngine.Core/Test.RazorEngine.Core.csproj @@ -164,6 +164,17 @@ Always + + + {5477469E-83B1-11D2-8B49-00A0C9B7C9C4} + 2 + 4 + 0 + tlbimp + False + True + +