Imported Upstream version 4.8.0.309

Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-11-10 13:04:39 +00:00
parent ee1447783b
commit 94b2861243
4912 changed files with 390737 additions and 49310 deletions

View File

@@ -7,6 +7,7 @@ namespace System.ServiceModel.Dispatcher
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
@@ -262,6 +263,7 @@ namespace System.ServiceModel.Dispatcher
}
}
[SuppressMessage("Microsoft.Security.Xml", "CA3057:DoNotUseLoadXml")]
static QueryMatcher()
{
QueryMatcher.defaultFunctionLibs = new IFunctionLibrary[] { new XPathFunctionLibrary() };

View File

@@ -8,12 +8,11 @@ namespace System.ServiceModel.Dispatcher
using System.Diagnostics;
using System.Reflection;
using System.Runtime;
using System.Runtime.Diagnostics;
using System.Security;
using System.ServiceModel.Description;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Diagnostics.Application;
using System.Threading.Tasks;
using Threading;
/// <summary>
/// An invoker used when some operation contract has a return value of Task or its generic counterpart (Task of T)
@@ -21,14 +20,12 @@ namespace System.ServiceModel.Dispatcher
internal class TaskMethodInvoker : IOperationInvoker
{
private const string ResultMethodName = "Result";
private MethodInfo taskMethod;
private bool isGenericTask;
private readonly MethodInfo taskMethod;
private InvokeDelegate invokeDelegate;
private int inputParameterCount;
private int outputParameterCount;
private object[] outputs;
private MethodInfo toAsyncMethodInfo;
private MethodInfo taskTResultGetMethod;
private bool isGenericTask;
public TaskMethodInvoker(MethodInfo taskMethod, Type taskType)
{
@@ -41,7 +38,6 @@ namespace System.ServiceModel.Dispatcher
if (taskType != ServiceReflector.VoidType)
{
this.toAsyncMethodInfo = TaskExtensions.MakeGenericMethod(taskType);
this.taskTResultGetMethod = ((PropertyInfo)taskMethod.ReturnType.GetMember(ResultMethodName)[0]).GetGetMethod();
this.isGenericTask = true;
}
@@ -57,36 +53,11 @@ namespace System.ServiceModel.Dispatcher
get { return this.taskMethod; }
}
private InvokeDelegate InvokeDelegate
{
get
{
this.EnsureIsInitialized();
return this.invokeDelegate;
}
}
private int InputParameterCount
{
get
{
this.EnsureIsInitialized();
return this.inputParameterCount;
}
}
private int OutputParameterCount
{
get
{
this.EnsureIsInitialized();
return this.outputParameterCount;
}
}
public object[] AllocateInputs()
{
return EmptyArray.Allocate(this.InputParameterCount);
EnsureIsInitialized();
return EmptyArray<object>.Allocate(this.inputParameterCount);
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
@@ -96,6 +67,114 @@ namespace System.ServiceModel.Dispatcher
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return ToApm(InvokeAsync(instance, inputs), callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
if (instance == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject)));
}
object returnVal = null;
bool callFailed = true;
bool callFaulted = false;
ServiceModelActivity activity = null;
Activity boundOperation = null;
try
{
AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation);
Task<Tuple<object, object[]>> invokeTask = result as Task<Tuple<object, object[]>>;
if (invokeTask == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.SFxInvalidCallbackIAsyncResult));
}
AggregateException ae = null;
Tuple<object, object[]> tuple = null;
Task task = null;
if (invokeTask.IsFaulted)
{
Fx.Assert(invokeTask.Exception != null, "Task.IsFaulted guarantees non-null exception.");
ae = invokeTask.Exception;
}
else
{
Fx.Assert(invokeTask.IsCompleted, "Task.Result is expected to be completed");
tuple = invokeTask.Result;
task = tuple.Item1 as Task;
if (task == null)
{
outputs = tuple.Item2;
return null;
}
if (task.IsFaulted)
{
Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception.");
ae = task.Exception;
}
}
if (ae != null && ae.InnerException != null)
{
if (ae.InnerException is FaultException)
{
// If invokeTask.IsFaulted we produce the 'callFaulted' behavior below.
// Any other exception will retain 'callFailed' behavior.
callFaulted = true;
callFailed = false;
}
if (ae.InnerException is SecurityException)
{
DiagnosticUtility.TraceHandledException(ae.InnerException, TraceEventType.Warning);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
}
invokeTask.GetAwaiter().GetResult();
}
// Task cancellation without an exception indicates failure but we have no
// additional information to provide. Accessing Task.Result will throw a
// TaskCanceledException. For consistency between void Tasks and Task<T>,
// we detect and throw here.
if (task.IsCanceled)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TaskCanceledException(task));
}
outputs = tuple.Item2;
returnVal = this.isGenericTask ? this.taskTResultGetMethod.Invoke(task, Type.EmptyTypes) : null;
callFailed = false;
return returnVal;
}
finally
{
if (boundOperation != null)
{
((IDisposable)boundOperation).Dispose();
}
ServiceModelActivity.Stop(activity);
AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
}
}
private async Task<Tuple<object, object[]>> InvokeAsync(object instance, object[] inputs)
{
EnsureIsInitialized();
if (instance == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject)));
@@ -103,59 +182,55 @@ namespace System.ServiceModel.Dispatcher
if (inputs == null)
{
if (this.InputParameterCount > 0)
if (this.inputParameterCount > 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.InputParameterCount)));
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.inputParameterCount)));
}
}
else if (inputs.Length != this.InputParameterCount)
else if (inputs.Length != this.inputParameterCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.InputParameterCount, inputs.Length)));
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.inputParameterCount, inputs.Length)));
}
this.outputs = EmptyArray.Allocate(this.OutputParameterCount);
object[] outputs = EmptyArray.Allocate(this.outputParameterCount);
AsyncMethodInvoker.StartOperationInvokePerformanceCounters(this.taskMethod.Name);
IAsyncResult returnValue;
bool callFailed = true;
bool callFaulted = false;
object returnValue;
ServiceModelActivity activity = null;
Activity boundActivity = null;
try
{
Activity boundActivity = null;
AsyncMethodInvoker.CreateActivityInfo(ref activity, ref boundActivity);
AsyncMethodInvoker.StartOperationInvokeTrace(this.taskMethod.Name);
using (boundActivity)
if (DiagnosticUtility.ShouldUseActivity)
{
if (DiagnosticUtility.ShouldUseActivity)
{
string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name);
ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode);
}
object taskReturnValue = this.InvokeDelegate(instance, inputs, this.outputs);
if (taskReturnValue == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task");
}
else if (this.isGenericTask)
{
returnValue = (IAsyncResult)this.toAsyncMethodInfo.Invoke(null, new object[] { taskReturnValue, callback, state });
}
else
{
returnValue = ((Task)taskReturnValue).AsAsyncResult(callback, state);
}
callFailed = false;
string activityName = SR.GetString(SR.ActivityExecuteMethod, this.taskMethod.DeclaringType.FullName, this.taskMethod.Name);
ServiceModelActivity.Start(activity, activityName, ActivityType.ExecuteUserCode);
}
OperationContext.EnableAsyncFlow();
returnValue = this.invokeDelegate(instance, inputs, outputs);
if (returnValue == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("task");
}
var returnValueTask = returnValue as Task;
if (returnValueTask != null)
{
// Only return once the task has completed
await returnValueTask;
}
return Tuple.Create(returnValue, outputs);
}
catch (System.Security.SecurityException e)
catch (SecurityException e)
{
DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
@@ -163,101 +238,77 @@ namespace System.ServiceModel.Dispatcher
catch (Exception e)
{
TraceUtility.TraceUserCodeException(e, this.taskMethod);
if (e is FaultException)
{
callFaulted = true;
callFailed = false;
}
throw;
}
finally
{
ServiceModelActivity.Stop(activity);
OperationContext.DisableAsyncFlow();
// Any exception above means InvokeEnd will not be called, so complete it here.
if (callFailed || callFaulted)
if (boundActivity != null)
{
AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
((IDisposable)boundActivity).Dispose();
}
}
return returnValue;
ServiceModelActivity.Stop(activity);
}
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
// Helper method when implementing an APM wrapper around a Task based async method which returns a result.
// In the BeginMethod method, you would call use ToApm to wrap a call to MethodAsync:
// return MethodAsync(params).ToApm(callback, state);
// In the EndMethod, you would use ToApmEnd<TResult> to ensure the correct exception handling
// This will handle throwing exceptions in the correct place and ensure the IAsyncResult contains the provided
// state object
private static Task<TResult> ToApm<TResult>(Task<TResult> task, AsyncCallback callback, object state)
{
object returnVal;
bool callFailed = true;
bool callFaulted = false;
ServiceModelActivity activity = null;
if (instance == null)
// When using APM, the returned IAsyncResult must have the passed in state object stored in AsyncState. This
// is so the callback can regain state. If the incoming task already holds the state object, there's no need
// to create a TaskCompletionSource to ensure the returned (IAsyncResult)Task has the right state object.
// This is a performance optimization for this special case.
if (task.AsyncState == state)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject)));
}
try
{
Activity boundOperation = null;
AsyncMethodInvoker.GetActivityInfo(ref activity, ref boundOperation);
using (boundOperation)
if (callback != null)
{
Task task = result as Task;
Fx.Assert(task != null, "InvokeEnd needs to be called with the result returned from InvokeBegin.");
if (task.IsFaulted)
task.ContinueWith((antecedent, obj) =>
{
Fx.Assert(task.Exception != null, "Task.IsFaulted guarantees non-null exception.");
// If FaultException is thrown, we will get 'callFaulted' behavior below.
// Any other exception will retain 'callFailed' behavior.
throw FxTrace.Exception.AsError<FaultException>(task.Exception);
}
// Task cancellation without an exception indicates failure but we have no
// additional information to provide. Accessing Task.Result will throw a
// TaskCanceledException. For consistency between void Tasks and Task<T>,
// we detect and throw here.
if (task.IsCanceled)
{
throw FxTrace.Exception.AsError(new TaskCanceledException(task));
}
outputs = this.outputs;
if (this.isGenericTask)
{
returnVal = this.taskTResultGetMethod.Invoke(result, Type.EmptyTypes);
}
else
{
returnVal = null;
}
callFailed = false;
AsyncCallback callbackObj = (AsyncCallback)obj;
callbackObj(antecedent);
}, callback, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default);
}
}
catch (SecurityException e)
{
DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException());
}
catch (FaultException)
{
callFaulted = true;
callFailed = false;
throw;
}
finally
{
ServiceModelActivity.Stop(activity);
AsyncMethodInvoker.StopOperationInvokeTrace(callFailed, callFaulted, this.TaskMethod.Name);
AsyncMethodInvoker.StopOperationInvokePerformanceCounters(callFailed, callFaulted, this.TaskMethod.Name);
return task;
}
return returnVal;
// Need to create a TaskCompletionSource so that the returned Task object has the correct AsyncState value.
var tcs = new TaskCompletionSource<TResult>(state);
var continuationState = Tuple.Create(tcs, callback);
task.ContinueWith((antecedent, obj) =>
{
Tuple<TaskCompletionSource<TResult>, AsyncCallback> tuple = (Tuple<TaskCompletionSource<TResult>, AsyncCallback>)obj;
TaskCompletionSource<TResult> tcsObj = tuple.Item1;
AsyncCallback callbackObj = tuple.Item2;
if (antecedent.IsFaulted)
{
tcsObj.TrySetException(antecedent.Exception.InnerException);
}
else if (antecedent.IsCanceled)
{
tcsObj.TrySetCanceled();
}
else
{
tcsObj.TrySetResult(antecedent.Result);
}
if (callbackObj != null)
{
callbackObj(tcsObj.Task);
}
}, continuationState, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default);
return tcs.Task;
}
private void EnsureIsInitialized()

View File

@@ -92,7 +92,7 @@ namespace System.ServiceModel.Dispatcher
bufferWriter.Flush();
XmlDocument doc = new XmlDocument();
memoryStream.Position = 0;
doc.Load(memoryStream);
doc.Load(new XmlTextReader(memoryStream) { DtdProcessing = DtdProcessing.Prohibit });
//doc.Save(Console.Out);
foreach (XmlElement element in doc.DocumentElement.ChildNodes)
{