You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,343 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.Runtime
|
||||
{
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Diagnostics;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
|
||||
abstract class ActionItem
|
||||
{
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores the security context, used later in binding back into")]
|
||||
[SecurityCritical]
|
||||
SecurityContext context;
|
||||
#endif
|
||||
bool isScheduled;
|
||||
|
||||
bool lowPriority;
|
||||
|
||||
protected ActionItem()
|
||||
{
|
||||
}
|
||||
|
||||
public bool LowPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.lowPriority;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
this.lowPriority = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Schedule(Action<object> callback, object state)
|
||||
{
|
||||
Schedule(callback, state, false);
|
||||
}
|
||||
[Fx.Tag.SecurityNote(Critical = "Calls into critical method ScheduleCallback",
|
||||
Safe = "Schedule invoke of the given delegate under the current context")]
|
||||
[SecuritySafeCritical]
|
||||
public static void Schedule(Action<object> callback, object state, bool lowPriority)
|
||||
{
|
||||
Fx.Assert(callback != null, "A null callback was passed for Schedule!");
|
||||
|
||||
if (PartialTrustHelpers.ShouldFlowSecurityContext ||
|
||||
WaitCallbackActionItem.ShouldUseActivity ||
|
||||
Fx.Trace.IsEnd2EndActivityTracingEnabled)
|
||||
{
|
||||
new DefaultActionItem(callback, state, lowPriority).Schedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
ScheduleCallback(callback, state, lowPriority);
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Called after applying the user context on the stack or (potentially) " +
|
||||
"without any user context on the stack")]
|
||||
[SecurityCritical]
|
||||
protected abstract void Invoke();
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Access critical field context and critical property " +
|
||||
"CallbackHelper.InvokeWithContextCallback, calls into critical method " +
|
||||
"PartialTrustHelpers.CaptureSecurityContextNoIdentityFlow, calls into critical method ScheduleCallback; " +
|
||||
"since the invoked method and the capturing of the security contex are de-coupled, can't " +
|
||||
"be treated as safe")]
|
||||
[SecurityCritical]
|
||||
protected void Schedule()
|
||||
{
|
||||
if (isScheduled)
|
||||
{
|
||||
throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.ActionItemIsAlreadyScheduled));
|
||||
}
|
||||
|
||||
this.isScheduled = true;
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
if (PartialTrustHelpers.ShouldFlowSecurityContext)
|
||||
{
|
||||
this.context = PartialTrustHelpers.CaptureSecurityContextNoIdentityFlow();
|
||||
}
|
||||
if (this.context != null)
|
||||
{
|
||||
ScheduleCallback(CallbackHelper.InvokeWithContextCallback);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ScheduleCallback(CallbackHelper.InvokeWithoutContextCallback);
|
||||
}
|
||||
}
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Access critical field context and critical property " +
|
||||
"CallbackHelper.InvokeWithContextCallback, calls into critical method ScheduleCallback; " +
|
||||
"since nothing is known about the given context, can't be treated as safe")]
|
||||
[SecurityCritical]
|
||||
protected void ScheduleWithContext(SecurityContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Fx.Exception.ArgumentNull("context");
|
||||
}
|
||||
if (isScheduled)
|
||||
{
|
||||
throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.ActionItemIsAlreadyScheduled));
|
||||
}
|
||||
|
||||
this.isScheduled = true;
|
||||
this.context = context.CreateCopy();
|
||||
ScheduleCallback(CallbackHelper.InvokeWithContextCallback);
|
||||
}
|
||||
#endif
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Access critical property CallbackHelper.InvokeWithoutContextCallback, " +
|
||||
"Calls into critical method ScheduleCallback; not bound to a security context")]
|
||||
[SecurityCritical]
|
||||
protected void ScheduleWithoutContext()
|
||||
{
|
||||
if (isScheduled)
|
||||
{
|
||||
throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.ActionItemIsAlreadyScheduled));
|
||||
}
|
||||
|
||||
this.isScheduled = true;
|
||||
ScheduleCallback(CallbackHelper.InvokeWithoutContextCallback);
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Calls into critical methods IOThreadScheduler.ScheduleCallbackNoFlow, " +
|
||||
"IOThreadScheduler.ScheduleCallbackLowPriNoFlow")]
|
||||
[SecurityCritical]
|
||||
static void ScheduleCallback(Action<object> callback, object state, bool lowPriority)
|
||||
{
|
||||
Fx.Assert(callback != null, "Cannot schedule a null callback");
|
||||
if (lowPriority)
|
||||
{
|
||||
IOThreadScheduler.ScheduleCallbackLowPriNoFlow(callback, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
IOThreadScheduler.ScheduleCallbackNoFlow(callback, state);
|
||||
}
|
||||
}
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Extract the security context stored and reset the critical field")]
|
||||
[SecurityCritical]
|
||||
SecurityContext ExtractContext()
|
||||
{
|
||||
Fx.Assert(this.context != null, "Cannot bind to a null context; context should have been set by now");
|
||||
Fx.Assert(this.isScheduled, "Context is extracted only while the object is scheduled");
|
||||
SecurityContext result = this.context;
|
||||
this.context = null;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
[Fx.Tag.SecurityNote(Critical = "Calls into critical static method ScheduleCallback")]
|
||||
[SecurityCritical]
|
||||
void ScheduleCallback(Action<object> callback)
|
||||
{
|
||||
ScheduleCallback(callback, this, this.lowPriority);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
static class CallbackHelper
|
||||
{
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores a delegate to a critical method")]
|
||||
static Action<object> invokeWithContextCallback;
|
||||
#endif
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores a delegate to a critical method")]
|
||||
static Action<object> invokeWithoutContextCallback;
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores a delegate to a critical method")]
|
||||
static ContextCallback onContextAppliedCallback;
|
||||
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Provides access to a critical field; Initialize it with " +
|
||||
"a delegate to a critical method")]
|
||||
public static Action<object> InvokeWithContextCallback
|
||||
{
|
||||
get
|
||||
{
|
||||
if (invokeWithContextCallback == null)
|
||||
{
|
||||
invokeWithContextCallback = new Action<object>(InvokeWithContext);
|
||||
}
|
||||
return invokeWithContextCallback;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
[Fx.Tag.SecurityNote(Critical = "Provides access to a critical field; Initialize it with " +
|
||||
"a delegate to a critical method")]
|
||||
public static Action<object> InvokeWithoutContextCallback
|
||||
{
|
||||
get
|
||||
{
|
||||
if (invokeWithoutContextCallback == null)
|
||||
{
|
||||
invokeWithoutContextCallback = new Action<object>(InvokeWithoutContext);
|
||||
}
|
||||
return invokeWithoutContextCallback;
|
||||
}
|
||||
}
|
||||
[Fx.Tag.SecurityNote(Critical = "Provides access to a critical field; Initialize it with " +
|
||||
"a delegate to a critical method")]
|
||||
public static ContextCallback OnContextAppliedCallback
|
||||
{
|
||||
get
|
||||
{
|
||||
if (onContextAppliedCallback == null)
|
||||
{
|
||||
onContextAppliedCallback = new ContextCallback(OnContextApplied);
|
||||
}
|
||||
return onContextAppliedCallback;
|
||||
}
|
||||
}
|
||||
#if FEATURE_COMPRESSEDSTACK
|
||||
[Fx.Tag.SecurityNote(Critical = "Called by the scheduler without any user context on the stack")]
|
||||
static void InvokeWithContext(object state)
|
||||
{
|
||||
SecurityContext context = ((ActionItem)state).ExtractContext();
|
||||
SecurityContext.Run(context, OnContextAppliedCallback, state);
|
||||
}
|
||||
#endif
|
||||
[Fx.Tag.SecurityNote(Critical = "Called by the scheduler without any user context on the stack")]
|
||||
static void InvokeWithoutContext(object state)
|
||||
{
|
||||
((ActionItem)state).Invoke();
|
||||
((ActionItem)state).isScheduled = false;
|
||||
}
|
||||
[Fx.Tag.SecurityNote(Critical = "Called after applying the user context on the stack")]
|
||||
static void OnContextApplied(object o)
|
||||
{
|
||||
((ActionItem)o).Invoke();
|
||||
((ActionItem)o).isScheduled = false;
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultActionItem : ActionItem
|
||||
{
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores a delegate that will be called later, at a particular context")]
|
||||
[SecurityCritical]
|
||||
Action<object> callback;
|
||||
[Fx.Tag.SecurityNote(Critical = "Stores an object that will be passed to the delegate that will be " +
|
||||
"called later, at a particular context")]
|
||||
[SecurityCritical]
|
||||
object state;
|
||||
|
||||
bool flowLegacyActivityId;
|
||||
Guid activityId;
|
||||
EventTraceActivity eventTraceActivity;
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Access critical fields callback and state",
|
||||
Safe = "Doesn't leak information or resources")]
|
||||
[SecuritySafeCritical]
|
||||
public DefaultActionItem(Action<object> callback, object state, bool isLowPriority)
|
||||
{
|
||||
Fx.Assert(callback != null, "Shouldn't instantiate an object to wrap a null callback");
|
||||
base.LowPriority = isLowPriority;
|
||||
this.callback = callback;
|
||||
this.state = state;
|
||||
if (WaitCallbackActionItem.ShouldUseActivity)
|
||||
{
|
||||
this.flowLegacyActivityId = true;
|
||||
this.activityId = EtwDiagnosticTrace.ActivityId;
|
||||
}
|
||||
if (Fx.Trace.IsEnd2EndActivityTracingEnabled)
|
||||
{
|
||||
this.eventTraceActivity = EventTraceActivity.GetFromThreadOrCreate();
|
||||
if (TraceCore.ActionItemScheduledIsEnabled(Fx.Trace))
|
||||
{
|
||||
TraceCore.ActionItemScheduled(Fx.Trace, this.eventTraceActivity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Implements a the critical abstract ActionItem.Invoke method, " +
|
||||
"Access critical fields callback and state")]
|
||||
[SecurityCritical]
|
||||
protected override void Invoke()
|
||||
{
|
||||
if (this.flowLegacyActivityId || Fx.Trace.IsEnd2EndActivityTracingEnabled)
|
||||
{
|
||||
TraceAndInvoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.callback(this.state);
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Implements a the critical abstract Trace method, " +
|
||||
"Access critical fields callback and state")]
|
||||
[SecurityCritical]
|
||||
void TraceAndInvoke()
|
||||
{
|
||||
//
|
||||
if (this.flowLegacyActivityId)
|
||||
{
|
||||
Guid currentActivityId = EtwDiagnosticTrace.ActivityId;
|
||||
try
|
||||
{
|
||||
EtwDiagnosticTrace.ActivityId = this.activityId;
|
||||
this.callback(this.state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EtwDiagnosticTrace.ActivityId = currentActivityId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Guid previous = Guid.Empty;
|
||||
bool restoreActivityId = false;
|
||||
try
|
||||
{
|
||||
if (this.eventTraceActivity != null)
|
||||
{
|
||||
previous = Trace.CorrelationManager.ActivityId;
|
||||
restoreActivityId = true;
|
||||
Trace.CorrelationManager.ActivityId = this.eventTraceActivity.ActivityId;
|
||||
if (TraceCore.ActionItemCallbackInvokedIsEnabled(Fx.Trace))
|
||||
{
|
||||
TraceCore.ActionItemCallbackInvoked(Fx.Trace, this.eventTraceActivity);
|
||||
}
|
||||
}
|
||||
this.callback(this.state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (restoreActivityId)
|
||||
{
|
||||
Trace.CorrelationManager.ActivityId = previous;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user