diff options
author | Daniel Harvey <dharvey@microsoft.com> | 2017-07-14 21:05:04 +0300 |
---|---|---|
committer | Daniel Harvey <dharvey@microsoft.com> | 2017-07-14 21:05:04 +0300 |
commit | aad567bc7b3965f4d10e7d5129fce833e5461c24 (patch) | |
tree | e90005fa5fb845938e81b83163945433153e68d2 /src | |
parent | 4eff7d02c1b2f49afeba46127a2a6f086ed6748f (diff) |
Makes exception dispatch call into AppContext to enable FirstChanceException. We're supposed to pass in an AppDomain as sender, but completing that will require a CoreFX change to pass in an AppDomain we can use.
[tfs-changeset: 1666024]
Diffstat (limited to 'src')
-rw-r--r-- | src/Native/Bootstrap/main.cpp | 2 | ||||
-rw-r--r-- | src/Native/Runtime/ICodeManager.h | 1 | ||||
-rw-r--r-- | src/Native/Runtime/inc/WellKnownMethodList.h | 1 | ||||
-rw-r--r-- | src/Native/Runtime/module.cpp | 3 | ||||
-rw-r--r-- | src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs | 23 | ||||
-rw-r--r-- | src/System.Private.CoreLib/src/System/AppContext.cs | 17 |
6 files changed, 46 insertions, 1 deletions
diff --git a/src/Native/Bootstrap/main.cpp b/src/Native/Bootstrap/main.cpp index 32e031a92..fc0209f5a 100644 --- a/src/Native/Bootstrap/main.cpp +++ b/src/Native/Bootstrap/main.cpp @@ -242,6 +242,7 @@ extern "C" void GetRuntimeException(); extern "C" void FailFast(); extern "C" void AppendExceptionStackFrame(); extern "C" void GetSystemArrayEEType(); +extern "C" void OnFirstChanceException(); typedef void(*pfn)(); @@ -252,6 +253,7 @@ static const pfn c_classlibFunctions[] = { &AppendExceptionStackFrame, nullptr, // &CheckStaticClassConstruction, &GetSystemArrayEEType, + &OnFirstChanceException }; #endif // !CPPCODEGEN diff --git a/src/Native/Runtime/ICodeManager.h b/src/Native/Runtime/ICodeManager.h index 016b8fd40..7cbfc1838 100644 --- a/src/Native/Runtime/ICodeManager.h +++ b/src/Native/Runtime/ICodeManager.h @@ -77,6 +77,7 @@ enum class ClasslibFunctionId AppendExceptionStackFrame = 3, CheckStaticClassConstruction = 4, GetSystemArrayEEType = 5, + OnFirstChanceException = 6, }; class ICodeManager diff --git a/src/Native/Runtime/inc/WellKnownMethodList.h b/src/Native/Runtime/inc/WellKnownMethodList.h index 75de3a58d..567764bbc 100644 --- a/src/Native/Runtime/inc/WellKnownMethodList.h +++ b/src/Native/Runtime/inc/WellKnownMethodList.h @@ -8,3 +8,4 @@ DEFINE_WELL_KNOWN_METHOD(UnhandledExceptionHandler) DEFINE_WELL_KNOWN_METHOD(AppendExceptionStackFrame) DEFINE_WELL_KNOWN_METHOD(CheckStaticClassConstruction) DEFINE_WELL_KNOWN_METHOD(InitializeFinalizerThread) +DEFINE_WELL_KNOWN_METHOD(OnFirstChanceException) diff --git a/src/Native/Runtime/module.cpp b/src/Native/Runtime/module.cpp index e8e9f7ed0..f17eb2857 100644 --- a/src/Native/Runtime/module.cpp +++ b/src/Native/Runtime/module.cpp @@ -821,6 +821,9 @@ void * Module::GetClasslibFunction(ClasslibFunctionId functionId) case ClasslibFunctionId::CheckStaticClassConstruction: pMethod = m_pModuleHeader->Get_CheckStaticClassConstruction(); break; + case ClasslibFunctionId::OnFirstChanceException: + pMethod = m_pModuleHeader->Get_OnFirstChanceException(); + break; default: pMethod = NULL; break; diff --git a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index aaf0cc33d..2b7fe6c75 100644 --- a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -155,6 +155,7 @@ namespace System.Runtime AppendExceptionStackFrame = 3, CheckStaticClassConstruction = 4, GetSystemArrayEEType = 5, + OnFirstChance = 6, } // Given an address pointing somewhere into a managed module, get the classlib-defined fail-fast @@ -211,6 +212,25 @@ namespace System.Runtime #endif } + private static void OnFirstChanceExceptionViaClassLib(object exception) + { + IntPtr pOnFirstChanceFunction = + (IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEtype((IntPtr)exception.m_pEEType, ClassLibFunctionId.OnFirstChance); + + if (pOnFirstChanceFunction == IntPtr.Zero) + { + return; + } + + try + { + CalliIntrinsics.CallVoid(pOnFirstChanceFunction, exception); + } + catch + { + // disallow all exceptions leaking out of callbacks + } + } [MethodImpl(MethodImplOptions.NoInlining)] internal static unsafe void UnhandledExceptionFailFastViaClasslib( @@ -647,7 +667,10 @@ namespace System.Runtime bool isValid = frameIter.Init(exInfo._pExContext, (exInfo._kind & ExKind.InstructionFaultFlag) != 0); Debug.Assert(isValid, "RhThrowEx called with an unexpected context"); + + OnFirstChanceExceptionViaClassLib(exceptionObj); DebuggerNotify.BeginFirstPass(exceptionObj, frameIter.ControlPC, frameIter.SP); + for (; isValid; isValid = frameIter.Next(out startIdx, out unwoundReversePInvoke)) { // For GC stackwalking, we'll happily walk across native code blocks, but for EH dispatch, we diff --git a/src/System.Private.CoreLib/src/System/AppContext.cs b/src/System.Private.CoreLib/src/System/AppContext.cs index 61dd6f701..6b316a448 100644 --- a/src/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/System.Private.CoreLib/src/System/AppContext.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Runtime; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -26,6 +27,9 @@ namespace System private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>(); private static Dictionary<String, Object> s_localStore = new Dictionary<String, Object>(); private static string s_defaultBaseDirectory; + // AppDomain lives in CoreFX, but some of this class's events need to pass in AppDomains, so people registering those + // events need to first pass in an AppDomain that we stash here to pass back in the events. + private static object s_appDomain; static AppContext() { @@ -33,6 +37,11 @@ namespace System AppContextDefaultValues.PopulateDefaultValues(); } + public static void SetAppDomain(object appDomain) + { + s_appDomain = appDomain; + } + public static string TargetFrameworkName => Assembly.GetEntryAssembly()?.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName; public static string BaseDirectory @@ -87,7 +96,7 @@ namespace System } } - private static void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs e) + internal static void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs e) { var firstChanceException = FirstChanceException; if (firstChanceException != null) @@ -96,6 +105,12 @@ namespace System } } + [RuntimeExport("OnFirstChanceException")] + internal static void OnFirstChanceException(object e) + { + OnFirstChanceException(s_appDomain, new FirstChanceExceptionEventArgs((Exception)e)); + } + private static void OnProcessExit(object sender, EventArgs e) { var processExit = ProcessExit; |