Skip to content

Commit

Permalink
Merge pull request dotnet#20963 from lmolkova/ActivityNoCrossAppDomain
Browse files Browse the repository at this point in the history
Store Activity wrapped into ObjectHandle in Logical CallContext
  • Loading branch information
vancem authored Jun 14, 2017
2 parents 72f74a6 + cb1c1df commit eaa04bd
Showing 1 changed file with 17 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Security;

namespace System.Diagnostics
{
// this code is specific to .NET 4.5 and uses CallContext to store Activity.Current which requires Activity to be Serializable.
[Serializable] // DO NOT remove
public partial class Activity
{
/// <summary>
Expand All @@ -22,26 +21,38 @@ public static Activity Current
#endif
get
{
return (Activity)CallContext.LogicalGetData(FieldKey);
ObjectHandle activityHandle = (ObjectHandle)CallContext.LogicalGetData(FieldKey);

// Unwrap the Activity if it was set in the same AppDomain (as FieldKey is AppDomain-specific).
if (activityHandle != null)
{
return (Activity)activityHandle.Unwrap();
}
return null;
}

#if ALLOW_PARTIALLY_TRUSTED_CALLERS
[System.Security.SecuritySafeCriticalAttribute]
#endif
private set
{
CallContext.LogicalSetData(FieldKey, value);
// Applications may implicitly or explicitly call other AppDomains
// that do not have DiagnosticSource DLL, therefore may not be able to resolve Activity type stored in the logical call context.
// To avoid it, we wrap Activity with ObjectHandle.
CallContext.LogicalSetData(FieldKey, new ObjectHandle(value));
}
}

#region private

[Serializable] // DO NOT remove
private partial class KeyValueListNode
{
}

private static readonly string FieldKey = $"{typeof(Activity).FullName}";
// Slot name depends on the AppDomain Id in order to prevent AppDomains to use the same Activity
// Cross AppDomain calls are considered as 'external' i.e. only Activity Id and Baggage should be propagated and
// new Activity should be started for the RPC calls (incoming and outgoing)
private static readonly string FieldKey = $"{typeof(Activity).FullName}_{AppDomain.CurrentDomain.Id}";
#endregion
}
}

0 comments on commit eaa04bd

Please sign in to comment.