From 496d94b41ffe13bc08023c1dfa50d9e4150be7c5 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 19 Jul 2016 13:10:29 -0700 Subject: [PATCH] Fix cross appdomain exception --- .../ElmScope.cs | 2 +- .../DataStoreErrorLogger.cs | 9 ++-- .../DataStoreErrorLoggerTest.cs | 46 +++++++++++++++++++ .../ElmLoggerTest.cs | 35 +++++++++++++- 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests/DataStoreErrorLoggerTest.cs diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmScope.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmScope.cs index 5db36960..dc9e78dc 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmScope.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmScope.cs @@ -26,7 +26,7 @@ public ElmScope(string name, object state) public ScopeNode Node { get; set; } #if NET451 - private static string FieldKey = typeof(ElmScope).FullName + ".Value"; + private static readonly string FieldKey = $"{typeof(ElmScope).FullName}.Value.{AppDomain.CurrentDomain.Id}"; public static ElmScope Current { get diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DataStoreErrorLogger.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DataStoreErrorLogger.cs index 3a15a749..09a67612 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DataStoreErrorLogger.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DataStoreErrorLogger.cs @@ -9,6 +9,7 @@ #if NETSTANDARD1_3 using System.Threading; #else +using System.Runtime.Remoting; using System.Runtime.Remoting.Messaging; #endif @@ -19,7 +20,7 @@ public class DataStoreErrorLogger : ILogger #if NETSTANDARD1_3 private readonly AsyncLocal _log = new AsyncLocal(); #else - private const string ContextName = "__DataStoreErrorLog"; + private static readonly string ContextName = "__DataStoreErrorLog" + AppDomain.CurrentDomain.Id; #endif public virtual DataStoreErrorLog LastError @@ -29,7 +30,9 @@ public virtual DataStoreErrorLog LastError #if NETSTANDARD1_3 return _log.Value; #else - return (DataStoreErrorLog)CallContext.LogicalGetData(ContextName); + var handle = CallContext.LogicalGetData(ContextName) as ObjectHandle; + + return handle?.Unwrap() as DataStoreErrorLog; #endif } } @@ -44,7 +47,7 @@ public virtual void StartLoggingForCurrentCallContext() #if NETSTANDARD1_3 _log.Value = new DataStoreErrorLog(); #else - CallContext.LogicalSetData(ContextName, new DataStoreErrorLog()); + CallContext.LogicalSetData(ContextName, new ObjectHandle(new DataStoreErrorLog())); #endif } diff --git a/test/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests/DataStoreErrorLoggerTest.cs b/test/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests/DataStoreErrorLoggerTest.cs new file mode 100644 index 00000000..b78a41b4 --- /dev/null +++ b/test/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests/DataStoreErrorLoggerTest.cs @@ -0,0 +1,46 @@ +using System; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests +{ +#if NET451 + public class DataStoreErrorLoggerTest + { + private const string _name = "test"; + + private static DataStoreErrorLogger SetUp(Func filter = null, string name = null) + { + // Arrange + var provider = new DataStoreErrorLoggerProvider(); + var logger = (DataStoreErrorLogger)provider.CreateLogger(name ?? _name); + + return logger; + } + + private static void DomainFunc() + { + var logger = SetUp(); + logger.StartLoggingForCurrentCallContext(); + logger.LogInformation(0, "Test"); + } + + [Fact] + public void ScopeWithChangingAppDomains_DoesNotAccessUnloadedAppDomain() + { + // Arrange + var logger = SetUp(); + var domain = AppDomain.CreateDomain("newDomain"); + + // Act + logger.StartLoggingForCurrentCallContext(); + domain.DoCallBack(DomainFunc); + AppDomain.Unload(domain); + logger.LogInformation(0, "Testing"); + + // Assert + Assert.NotNull(logger.LastError); + } + } +#endif +} diff --git a/test/Microsoft.AspNetCore.Diagnostics.Tests/ElmLoggerTest.cs b/test/Microsoft.AspNetCore.Diagnostics.Tests/ElmLoggerTest.cs index cdd7c7e4..6c22e325 100644 --- a/test/Microsoft.AspNetCore.Diagnostics.Tests/ElmLoggerTest.cs +++ b/test/Microsoft.AspNetCore.Diagnostics.Tests/ElmLoggerTest.cs @@ -16,9 +16,9 @@ public class ElmLoggerTest { private const string _name = "test"; private const string _state = "This is a test"; - private Func _filter = (_, __) => true; + private static Func _filter = (_, __) => true; - private Tuple SetUp(Func filter = null, string name = null) + private static Tuple SetUp(Func filter = null, string name = null) { // Arrange var store = new ElmStore(); @@ -305,6 +305,37 @@ public void CollapseTree_WorksWithFilter() Assert.Empty(store.GetActivities()); } +#if NET451 + private static void DomainFunc() + { + var t = SetUp(); + var logger = t.Item1; + using (logger.BeginScope("newDomain scope")) + { + logger.LogInformation("Test"); + } + } + + [Fact] + public void ScopeWithChangingAppDomains_DoesNotAccessUnloadedAppDomain() + { + // Arrange + var t = SetUp(); + var logger = t.Item1; + var store = t.Item2; + var domain = AppDomain.CreateDomain("newDomain"); + + // Act + domain.DoCallBack(DomainFunc); + AppDomain.Unload(domain); + using (logger.BeginScope("Scope1")) + { + logger.LogInformation("Testing"); + } + + Assert.Equal(1, store.Count()); + } +#endif private List NodeLogs(ScopeNode node, List logs) {