Skip to content

Commit

Permalink
LogContext's remoting issue fix for .NET 4.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Komisarchik committed Jul 1, 2017
1 parent 62f26ff commit 2f4949f
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 3 deletions.
32 changes: 31 additions & 1 deletion src/Serilog/Context/LogContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using System.Threading;
#elif REMOTING
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Messaging;
#endif

Expand Down Expand Up @@ -207,7 +208,36 @@ static ImmutableStack<ILogEventEnricher> Enrichers
}
set
{
CallContext.LogicalSetData(DataSlotName, new ObjectHandle(value));
if (CallContext.LogicalGetData(DataSlotName) is IDisposable oldHandle)
{
oldHandle.Dispose();
}

CallContext.LogicalSetData(DataSlotName, new DisposableObjectHandle(value));
}
}

sealed class DisposableObjectHandle : ObjectHandle, IDisposable
{
static readonly ISponsor LifeTimeSponsor = new ClientSponsor();

public DisposableObjectHandle(object o) : base(o)
{
}

public override object InitializeLifetimeService()
{
var lease = (ILease)base.InitializeLifetimeService();
lease.Register(LifeTimeSponsor);
return lease;
}

public void Dispose()
{
if (GetLifetimeService() is ILease lease)
{
lease.Unregister(LifeTimeSponsor);
}
}
}

Expand Down
96 changes: 94 additions & 2 deletions test/Serilog.Tests/Context/LogContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using Serilog.Tests.Support;
#if APPDOMAIN
using System;
using System.IO;
#endif
#if REMOTING
using System.Runtime.Remoting;
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting.Services;
using System.Runtime.Remoting.Messaging;
#endif
using System.Threading;
Expand All @@ -18,6 +20,14 @@ namespace Serilog.Tests.Context
{
public class LogContextTests
{
static LogContextTests()
{
#if REMOTING
LifetimeServices.LeaseTime = TimeSpan.FromMilliseconds(100);
LifetimeServices.LeaseManagerPollTime = TimeSpan.FromMilliseconds(10);
#endif
}

public LogContextTests()
{
#if REMOTING
Expand Down Expand Up @@ -212,9 +222,91 @@ public void DoesNotPreventCrossDomainCalls()
}
}
#endif

#if APPDOMAIN && REMOTING
[Fact]
public void DoesNotThrowOnCrossDomainCallsWhenLeaseExpired()
{
// Arrange
RemotingException remotingException = null;

AppDomain.CurrentDomain.FirstChanceException +=
(_, e) => remotingException = e.Exception is RemotingException re ? re : remotingException;

var logger = new LoggerConfiguration().Enrich.FromLogContext().CreateLogger();
var remote = AppDomain.CreateDomain("Remote", null, AppDomain.CurrentDomain.SetupInformation);

// Act
try
{
using (LogContext.PushProperty("Prop", 42))
{
remote.DoCallBack(CallFromRemote);
logger.Information("Prop = {Prop}");
}
}
finally
{
AppDomain.Unload(remote);
}

// Assert
Assert.Null(remotingException);

void CallFromRemote() => Thread.Sleep(200);
}

[Fact]
public async Task DisconnectRemoteObjectsAfterCrossDomainCallsOnDispose()
{
// Arrange
var tracker = new InMemoryRemoteObjectTracker();
TrackingServices.RegisterTrackingHandler(tracker);

var remote = AppDomain.CreateDomain("Remote", null, AppDomain.CurrentDomain.SetupInformation);

// Act
try
{
using (LogContext.PushProperty("Prop1", 42))
{
remote.DoCallBack(CallFromRemote);

using (LogContext.PushProperty("Prop2", 24))
{
remote.DoCallBack(CallFromRemote);
}
}
}
finally
{
AppDomain.Unload(remote);
}

await Task.Delay(200);

// Assert
Assert.Equal(2, tracker.DisconnectCount);

void CallFromRemote() { }
}
#endif
}

#if REMOTING
class InMemoryRemoteObjectTracker : ITrackingHandler
{
public int DisconnectCount { get; set; }

public void DisconnectedObject(object obj) => DisconnectCount++;

public void MarshaledObject(object obj, ObjRef or) { }

public void UnmarshaledObject(object obj, ObjRef or) { }
}
#endif

#if REMOTING || APPDOMAIN
#if APPDOMAIN
public class RemotelyCallable : MarshalByRefObject
{
public bool IsCallable()
Expand Down

0 comments on commit 2f4949f

Please sign in to comment.