<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeFeature.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeDependencyAttribute.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\GcSettings.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ArrayWithOffset.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Attributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Consistency.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\CriticalFinalizerObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\ReliabilityContractAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\ExceptionNotification.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\HandleProcessCorruptedStateExceptionsAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\BestFitMappingAttribute.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// 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.Diagnostics;
+
+namespace System.Runtime.ExceptionServices
+{
+ // This class defines support for separating the exception dispatch details
+ // (like stack trace, watson buckets, etc) from the actual managed exception
+ // object. This allows us to track error (via the exception object) independent
+ // of the path the error takes.
+ //
+ // This is particularly useful for frameworks that wish to propagate
+ // exceptions (i.e. errors to be precise) across threads.
+ public sealed class ExceptionDispatchInfo
+ {
+ private readonly Exception _exception;
+ private readonly Exception.DispatchState _dispatchState;
+
+ private ExceptionDispatchInfo(Exception exception)
+ {
+ _exception = exception;
+ _dispatchState = exception.CaptureDispatchState();
+ }
+
+ // This static method is used to create an instance of ExceptionDispatchInfo for
+ // the specified exception object and save all the required details that maybe
+ // needed to be propagated when the exception is "rethrown" on a different thread.
+ public static ExceptionDispatchInfo Capture(Exception source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ return new ExceptionDispatchInfo(source);
+ }
+
+ // Return the exception object represented by this ExceptionDispatchInfo instance
+ public Exception SourceException
+ {
+ get
+ {
+ return _exception;
+ }
+ }
+
+ // When a framework needs to "Rethrow" an exception on a thread different (but not necessarily so) from
+ // where it was thrown, it should invoke this method against the ExceptionDispatchInfo
+ // created for the exception in question.
+ //
+ // This method will restore the original stack trace and bucketing details before throwing
+ // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
+ // the original thread.
+ [StackTraceHidden]
+ public void Throw()
+ {
+ // Restore the exception dispatch details before throwing the exception.
+ _exception.RestoreDispatchState(_dispatchState);
+ throw _exception;
+ }
+
+ // Throws the source exception, maintaining the original bucketing details and augmenting
+ // rather than replacing the original stack trace.
+ public static void Throw(Exception source) => Capture(source).Throw();
+ }
+}
**
=============================================================================*/
+using System.Collections;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+
namespace System
{
- using System;
- using System.Runtime.InteropServices;
- using System.Runtime.CompilerServices;
- using System.Runtime.Serialization;
- using System.Runtime.Versioning;
- using System.Diagnostics;
- using System.Security;
- using System.IO;
- using System.Text;
- using System.Reflection;
- using System.Collections;
- using System.Globalization;
-
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class Exception : ISerializable
{
- private void Init()
+ public Exception()
{
_message = null;
_stackTrace = null;
_ipForWatsonBuckets = UIntPtr.Zero;
}
- public Exception()
- {
- Init();
- }
-
public Exception(string message)
+ : this()
{
- Init();
_message = message;
}
// is thrown
//
public Exception(string message, Exception innerException)
+ : this()
{
- Init();
_message = message;
_innerException = innerException;
}
{
get
{
- return GetTargetSiteInternal();
- }
- }
-
+ if (_exceptionMethod != null)
+ {
+ return _exceptionMethod;
+ }
+ if (_stackTrace == null)
+ {
+ return null;
+ }
- // this function is provided as a private helper to avoid the security demand
- private MethodBase GetTargetSiteInternal()
- {
- if (_exceptionMethod != null)
- {
+ _exceptionMethod = GetExceptionMethodFromStackTrace();
return _exceptionMethod;
}
- if (_stackTrace == null)
- {
- return null;
- }
-
- _exceptionMethod = GetExceptionMethodFromStackTrace();
- return _exceptionMethod;
}
// Returns the stack trace as a string. If no stack trace is
// for a small duration but that sounds reasonable considering
// such scenarios are going to be extremely rare, where timing
// matches precisely.
- [OptionalField]
- private static object s_EDILock = new object();
-
- internal UIntPtr IPForWatsonBuckets
- {
- get
- {
- return _ipForWatsonBuckets;
- }
- }
-
- internal object WatsonBuckets
- {
- get
- {
- return _watsonBuckets;
- }
- }
-
- internal string RemoteStackTrace
- {
- get
- {
- return _remoteStackTraceString;
- }
- }
+ private static readonly object s_DispatchStateLock = new object();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void PrepareForForeignExceptionRaise();
}
}
- internal void GetStackTracesDeepCopy(out object currentStackTrace, out object dynamicMethodArray)
- {
- GetStackTracesDeepCopy(this, out currentStackTrace, out dynamicMethodArray);
- }
-
// This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the
// exception, just before the exception is "rethrown".
- internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
+ internal void RestoreDispatchState(in DispatchState dispatchState)
{
bool fCanProcessException = !(IsImmutableAgileException(this));
// Restore only for non-preallocated exceptions
//
// Since deep copying can throw on OOM, try to get the copies
// outside the lock.
- object _stackTraceCopy = (exceptionDispatchInfo.BinaryStackTraceArray == null) ? null : DeepCopyStackTrace(exceptionDispatchInfo.BinaryStackTraceArray);
- object _dynamicMethodsCopy = (exceptionDispatchInfo.DynamicMethodArray == null) ? null : DeepCopyDynamicMethods(exceptionDispatchInfo.DynamicMethodArray);
+ object _stackTraceCopy = (dispatchState.StackTrace == null) ? null : DeepCopyStackTrace(dispatchState.StackTrace);
+ object _dynamicMethodsCopy = (dispatchState.DynamicMethods == null) ? null : DeepCopyDynamicMethods(dispatchState.DynamicMethods);
// Finally, restore the information.
//
// Since EDI can be created at various points during exception dispatch (e.g. at various frames on the stack) for the same exception instance,
// they can have different data to be restored. Thus, to ensure atomicity of restoration from each EDI, perform the restore under a lock.
- lock (Exception.s_EDILock)
+ lock (s_DispatchStateLock)
{
- _watsonBuckets = exceptionDispatchInfo.WatsonBuckets;
- _ipForWatsonBuckets = exceptionDispatchInfo.IPForWatsonBuckets;
- _remoteStackTraceString = exceptionDispatchInfo.RemoteStackTrace;
+ _watsonBuckets = dispatchState.WatsonBuckets;
+ _ipForWatsonBuckets = dispatchState.IpForWatsonBuckets;
+ _remoteStackTraceString = dispatchState.RemoteStackTrace;
SaveStackTracesFromDeepCopy(this, _stackTraceCopy, _dynamicMethodsCopy);
}
_stackTraceString = null;
// Marks the TES state to indicate we have restored foreign exception
// dispatch information.
- Exception.PrepareForForeignExceptionRaise();
+ PrepareForForeignExceptionRaise();
}
}
}
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void GetMessageFromNativeResources(ExceptionMessageKind kind, StringHandleOnStack retMesg);
+
+ internal readonly struct DispatchState
+ {
+ public readonly object StackTrace;
+ public readonly object DynamicMethods;
+ public readonly string RemoteStackTrace;
+ public readonly UIntPtr IpForWatsonBuckets;
+ public readonly object WatsonBuckets;
+
+ public DispatchState(
+ object stackTrace,
+ object dynamicMethods,
+ string remoteStackTrace,
+ UIntPtr ipForWatsonBuckets,
+ object watsonBuckets)
+ {
+ StackTrace = stackTrace;
+ DynamicMethods = dynamicMethods;
+ RemoteStackTrace = remoteStackTrace;
+ IpForWatsonBuckets = ipForWatsonBuckets;
+ WatsonBuckets = watsonBuckets;
+ }
+ }
+
+ internal DispatchState CaptureDispatchState()
+ {
+ GetStackTracesDeepCopy(this, out object stackTrace, out object dynamicMethods);
+
+ return new DispatchState(stackTrace, dynamicMethods,
+ _remoteStackTraceString, _ipForWatsonBuckets, _watsonBuckets);
+ }
}
}
-
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*=============================================================================
-**
-**
-**
-** Purpose: Contains common usage support entities for advanced exception
-** handling/processing scenarios.
-**
-** Created: 11/2/2010
-**
-**
-**
-=============================================================================*/
-
-using System;
-using System.Diagnostics;
-
-namespace System.Runtime.ExceptionServices
-{
- // This class defines support for seperating the exception dispatch details
- // (like stack trace, watson buckets, etc) from the actual managed exception
- // object. This allows us to track error (via the exception object) independent
- // of the path the error takes.
- //
- // This is particularly useful for frameworks like PFX, APM, etc that wish to
- // propagate exceptions (i.e. errors to be precise) across threads.
- public sealed class ExceptionDispatchInfo
- {
- // Private members that will hold the relevant details.
- private Exception m_Exception;
- private string m_remoteStackTrace;
- private object m_stackTrace;
- private object m_dynamicMethods;
- private UIntPtr m_IPForWatsonBuckets;
- private object m_WatsonBuckets;
-
- private ExceptionDispatchInfo(Exception exception)
- {
- // Copy over the details we need to save.
- m_Exception = exception;
- m_remoteStackTrace = exception.RemoteStackTrace;
-
- // NOTE: don't be tempted to pass the fields for the out params; the containing object
- // might be relocated during the call so the pointers will no longer be valid.
- object stackTrace;
- object dynamicMethods;
- m_Exception.GetStackTracesDeepCopy(out stackTrace, out dynamicMethods);
- m_stackTrace = stackTrace;
- m_dynamicMethods = dynamicMethods;
-
- m_IPForWatsonBuckets = exception.IPForWatsonBuckets;
- m_WatsonBuckets = exception.WatsonBuckets;
- }
-
- internal UIntPtr IPForWatsonBuckets
- {
- get
- {
- return m_IPForWatsonBuckets;
- }
- }
-
- internal object WatsonBuckets
- {
- get
- {
- return m_WatsonBuckets;
- }
- }
-
- internal object BinaryStackTraceArray
- {
- get
- {
- return m_stackTrace;
- }
- }
-
- internal object DynamicMethodArray
- {
- get
- {
- return m_dynamicMethods;
- }
- }
-
- internal string RemoteStackTrace
- {
- get
- {
- return m_remoteStackTrace;
- }
- }
-
- // This static method is used to create an instance of ExceptionDispatchInfo for
- // the specified exception object and save all the required details that maybe
- // needed to be propagated when the exception is "rethrown" on a different thread.
- public static ExceptionDispatchInfo Capture(Exception source)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source), SR.ArgumentNull_Obj);
- }
-
- return new ExceptionDispatchInfo(source);
- }
-
- // Return the exception object represented by this ExceptionDispatchInfo instance
- public Exception SourceException
- {
- get
- {
- return m_Exception;
- }
- }
-
- // When a framework needs to "Rethrow" an exception on a thread different (but not necessarily so) from
- // where it was thrown, it should invoke this method against the ExceptionDispatchInfo (EDI)
- // created for the exception in question.
- //
- // This method will restore the original stack trace and bucketing details before throwing
- // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
- // the original thread.
- [StackTraceHidden]
- public void Throw()
- {
- // Restore the exception dispatch details before throwing the exception.
- m_Exception.RestoreExceptionDispatchInfo(this);
- throw m_Exception;
- }
-
- // Throws the source exception, maintaining the original bucketing details and augmenting
- // rather than replacing the original stack trace.
- public static void Throw(Exception source) => Capture(source).Throw();
- }
-}