Open mattjohnsonpint opened 2 years ago
A potential workaround would be to add event handlers to the Runtime.MarshalManagedException
and Runtime.MarshalObjectiveCException
events and handle those as you handle AppDomain.CurrentDomain.UnhandledException
.
Ref: https://docs.microsoft.com/en-us/xamarin/ios/platform/exception-marshaling#events
Thanks. After testing with those, I find that by default the same thing happens there as well. MarshalManagedException
fires thousands of times. MarshalObjectiveCException
never fires.
However, if I set the ExceptionMode
to UnwindNativeCode
in MarshalManagedException
, then things start looking more like I expect them to.
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
Console.WriteLine("In UnhandledException Handler");
};
AppDomain.CurrentDomain.FirstChanceException += (sender, args) =>
{
Console.WriteLine("In FirstChanceException Handler");
};
ObjCRuntime.Runtime.MarshalManagedException += (sender, args) =>
{
Console.WriteLine("In MarshalManagedException Handler");
args.ExceptionMode = ObjCRuntime.MarshalManagedExceptionMode.UnwindNativeCode;
};
ObjCRuntime.Runtime.MarshalObjectiveCException += (sender, args) =>
{
Console.WriteLine("In MarshalObjectiveCException Handler");
};
throw new Exception("Test Exception");
My debug output now includes the following:
2022-06-13 10:31:30.161041-0700 IosApp1[48797:2241605] In FirstChanceException Handler
2022-06-13 10:31:30.163774-0700 IosApp1[48797:2241605] In MarshalManagedException Handler
2022-06-13 10:31:30.166228-0700 IosApp1[48797:2241605] In FirstChanceException Handler
2022-06-13 10:31:30.166646-0700 IosApp1[48797:2241605] In FirstChanceException Handler
2022-06-13 10:31:30.167401-0700 IosApp1[48797:2241605] In UnhandledException Handler
2022-06-13 10:31:30.226152-0700 IosApp1[48797:2241605] Unhandled managed exception: Test Exception (System.Exception)
at IosApp1.AppDelegate.FinishedLaunching(UIApplication application, NSDictionary launchOptions) in /Users/matt/Code/IosApp1/AppDelegate.cs:line 51
So it seems I can workaround the issue for now by using MarshalManagedException
to change the exception mode to UnwindNativeCode
, and then just using AppDomain.CurrentDomain.UnhandledException
as normal. Does that sound right to you?
I am a bit confused why this works though. The doc you pointed at says:
Default
: The default varies by platform. It's alwaysThrowObjectiveCException
in .NET. For legacy Xamarin projects, it'sThrowObjectiveCException
if the GC is in cooperative mode (watchOS), andUnwindNativeCode
otherwise (iOS / watchOS / macOS). The default may change in the future.UnwindNativeCode
: This is the previous (undefined) behavior. This isn't available when using the GC in cooperative mode (which is the only option on watchOS; thus, this isn't a valid option on watchOS), nor when using CoreCLR, but it's the default option for all other platforms in legacy Xamarin projects.
So, why does setting UnwindNativeCode
in an iOS project change anything, when the docs say that's the default mode for iOS? Could it be because I'm running in a simulator?
So, why does setting
UnwindNativeCode
in an iOS project change anything, when the docs say that's the default mode for iOS? Could it be because I'm running in a simulator?
We changed the default in .NET, and that page hasn't been updated yet:
So it seems I can workaround the issue for now by using
MarshalManagedException
to change the exception mode toUnwindNativeCode
, and then just usingAppDomain.CurrentDomain.UnhandledException
as normal. Does that sound right to you?
Yes, I think that should work fine.
Thanks!
Confirming that the same problem exists for macOS applications, and that setting the exception mode to Unwind doesn't seem to make AppDomain.CurrentDomain.UnhandledException
trigger. Currently using the workaround described by @rolfbjarne (just putting my custom exception logging code in MarshalManagedException
and MarshalObjectiveCException
).
I think the comments in this file also have to be updated to reflect what is now the default: https://github.com/xamarin/xamarin-macios/blob/main/src/ObjCRuntime/ExceptionMode.cs
A potential workaround would be to add event handlers to the
Runtime.MarshalManagedException
andRuntime.MarshalObjectiveCException
events and handle those as you handleAppDomain.CurrentDomain.UnhandledException
.Ref: https://docs.microsoft.com/en-us/xamarin/ios/platform/exception-marshaling#events
@rolfbjarne Does this workaround apply to Xamarin.iOS as well? It seems that Runtime.MarshalManagedException, Runtime.MarshalObjectiveCException and AppDomain.CurrentDomain.UnhandledException don't trigger at all in Release mode in Xamarin.iOS unless --interpreter=all is set. Unfortunately, enabling the interpreter in Xamarin.iOS for us is a huge performance hit.
A potential workaround would be to add event handlers to the
Runtime.MarshalManagedException
andRuntime.MarshalObjectiveCException
events and handle those as you handleAppDomain.CurrentDomain.UnhandledException
. Ref: docs.microsoft.com/en-us/xamarin/ios/platform/exception-marshaling#events@rolfbjarne Does this workaround apply to Xamarin.iOS as well? It seems that Runtime.MarshalManagedException, Runtime.MarshalObjectiveCException and AppDomain.CurrentDomain.UnhandledException don't trigger at all in Release mode in Xamarin.iOS unless --interpreter=all is set. Unfortunately, enabling the interpreter in Xamarin.iOS for us is a huge performance hit.
Yes, but you must explicitly enable exception marshalling (we turned it on by default in .NET).
You can do that by adding this to the additional mtouch arguments in the project's iOS Build options (this is the MtouchExtraArgs property in the csproj).
--marshal-managed-exceptions=throwobjectivecexception --marshal-objectivec-exceptions=throwmanagedexception
Has this issue been resolved in .NET 7?
Confirming that the same problem exists for macOS applications, and that setting the exception mode to Unwind doesn't seem to make
AppDomain.CurrentDomain.UnhandledException
trigger. Currently using the workaround described by @rolfbjarne (just putting my custom exception logging code inMarshalManagedException
andMarshalObjectiveCException
).
For a .NET 7 macOS application, it looks like the AppDomain.UnhandledException is not triggered at all. I tested it by throwing a managed exception on the main thread. I can see that the Runtime.MarshalManagedException is fired, but then setting the ExceptionMode to UnwindNativeCode doesn't fire the UnhandledException either, it just crashes the app.
Has this issue been resolved in .NET 7?
No, it's not been fixed yet.
A few updates:
The log shows that the
FirstChanceException
handler fires over 1000 times
This has been fixed (9b8869b2210068bdfce38e9a2f88ed40e69fed2d).
In my test case, FirstChanceException
is printed four times:
FirstChanceException
).We can probably fix the fourth, but we likely won't be able to fix the second and third.
The
UnhandledException
handler never fires.
This is not fixed. In fact there doesn't seem to be a way for us to call this handler, the managed runtime does it automatically during exception handler. Unfortunately we're somewhat exceptional, so the existing logic in the managed runtime doesn't work for us.
I've filed https://github.com/dotnet/runtime/issues/102730 to see if we can find a way to raise the UnhandledException event.
The problem with the UnhandledException
event not being raised has been fixed when using MonoVM (this means on iOS, Mac Catalyst and tvOS, as long as you're not using NativeAOT). It's still a problem when using CoreCLR (on macOS or when using NativeAOT).
Steps to Reproduce
On a Mac, after installing the latest 6.0.300 SDK and the
ios
workload:dotnet new ios
Edit
AppDelegate.cs
. At the end ofFinishedLaunching
, beforereturn true;
insert the following code:dotnet run
Expected Behavior
The output should indicate that the
FirstChanceException
handler fires once, and then theUnhandledException
handler should fire once. Then I should get a crash report window from macOS (if applicable).Actual Behavior
The log shows that the
FirstChanceException
handler fires over 1000 times (the exact number seems to vary). TheUnhandledException
handler never fires. I do get the crash report window from macOS.Environment
Version information
``` Visual Studio Enterprise 2022 for Mac Preview Version 17.3 Preview (17.3 build 198) Installation UUID: 1a1c51f5-b451-405d-a88b-c8682f3c4d95 Runtime .NET 6.0.3 (64-bit) Architecture: Arm64 Roslyn (Language Service) 4.2.0-3.22181.8+a59a22c6f3c2cc1883e20cece412209f18f4a29f NuGet Version: 6.0.0.262 .NET SDK (Arm64) SDK: /usr/local/share/dotnet/sdk/6.0.300/Sdks SDK Version: 6.0.300 MSBuild SDKs: /usr/local/share/dotnet/sdk/6.0.300/Sdks .NET SDK (x64) SDK Versions: 6.0.300 5.0.408 3.1.419 2.1.818 .NET Runtime (Arm64) Runtime: /usr/local/share/dotnet/dotnet Runtime Version: 6.0.5 .NET Runtime (x64) Runtime: /usr/local/share/dotnet/x64/dotnet Runtime Versions: 6.0.5 5.0.17 3.1.25 2.1.30 Xamarin.Profiler Version: 1.8.0.19 Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler Updater Version: 11 Apple Developer Tools Xcode 13.4.1 (20504) Build 13F100 Xamarin.Mac Version: 8.10.0.1 (Visual Studio Enterprise) Hash: 568bdb24e Branch: d17-2 Build date: 2022-04-08 18:52:56-0400 Xamarin.iOS Version: 15.10.0.1 (Visual Studio Enterprise) Hash: 568bdb24e Branch: d17-2 Build date: 2022-04-08 18:52:57-0400 Xamarin Designer Version: 17.3.0.70 Hash: 4cf1a2208 Branch: remotes/origin/d17-3 Build date: 2022-05-25 15:22:03 UTC Xamarin.Android Version: 12.3.99.58 (Visual Studio Enterprise) Commit: xamarin-android/main/64b22fc Android SDK: /Users/matt/Library/Android/sdk Supported Android versions: 12.1 (API level 32) 12.0 (API level 31) 11.0 (API level 30) 9.0 (API level 28) SDK Command-line Tools Version: 5.0 SDK Platform Tools Version: 33.0.1 SDK Build Tools Version: 33.0.0 rc4 Build Information: Mono: adf1bc4 Java.Interop: xamarin/java.interop/release/6.0.3xx@2a882d2d ProGuard: Guardsquare/proguard/v7.0.1@912d149 SQLite: xamarin/sqlite/3.38.2@7b1e016 Xamarin.Android Tools: xamarin/xamarin-android-tools/main@fc3c2ac Microsoft Build of OpenJDK Java SDK: /Library/Java/JavaVirtualMachines/microsoft-11.jdk 11.0.15 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Eclipse Temurin JDK Java SDK: /Library/Java/JavaVirtualMachines/temurin-8.jdk 1.8.0.302 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Android SDK Manager Version: 17.2.0.47 Hash: d6dd135 Branch: remotes/origin/dev/tondat/main-1512059~2 Build date: 2022-05-25 15:21:57 UTC Android Device Manager Version: 0.0.0.1127 Hash: 4bb4d48 Branch: remotes/origin/dev/tondat/main-1536295~1 Build date: 2022-05-25 15:21:57 UTC Build Information Release ID: 1703000198 Git revision: b61a5879556b3b4d5270ffffd9431e5ec7db233d Build date: 2022-05-25 15:20:15+00 Build branch: release-17.3 Build lane: release-17.3 Operating System Mac OS X 12.4.0 Darwin 21.5.0 Darwin Kernel Version 21.5.0 Tue Apr 26 21:08:37 PDT 2022 root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 arm64 ```Crash Report
``` ------------------------------------- Translated Report (Full Report Below) ------------------------------------- Incident Identifier: A43C9AF2-C7F0-4138-8A6F-13803FED9E14 CrashReporter Key: 033C27F8-F8D2-CF5C-D530-420FAA271D3D Hardware Model: MacBookPro18,1 Process: IosApp1 [88916] Path: /Users/USER/Library/Developer/CoreSimulator/Devices/02F1B274-3BDC-471F-9304-EC96459FB2BC/data/Containers/Bundle/Application/8F088341-30E9-4168-81FF-61B555F0DF29/IosApp1.app/IosApp1 Identifier: com.companyname.IosApp1 Version: 1.0 (1.0) Code Type: X86-64 (Native) Role: Foreground Parent Process: launchd_sim [25203] Coalition: com.apple.CoreSimulator.SimDevice.02F1B274-3BDC-471F-9304-EC96459FB2BC [9251] Responsible Process: SimulatorTrampoline [1443] Date/Time: 2022-06-11 15:36:42.3685 -0700 Launch Time: 2022-06-11 15:36:39.7411 -0700 OS Version: macOS 12.4 (21F79) Release Type: User Report Version: 104 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_PROTECTION_FAILURE at 0x000000030c5dbb34 Exception Codes: 0x0000000000000002, 0x000000030c5dbb34 VM Region Info: 0x30c5dbb34 is in 0x308dd8000-0x30c5dc000; bytes after start: 58735412 bytes before end: 1227 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL unused shlib __TEXT 2049c2000-2049c5000 [ 12K] r--/r-- SM=NUL ... this process GAP OF 0x104413000 BYTES ---> Stack Guard 308dd8000-30c5dc000 [ 56.0M] ---/rwx SM=NUL Stack 30c5dc000-30cdd8000 [ 8176K] rw-/rwx SM=PRV Exception Note: EXC_CORPSE_NOTIFY Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [88916] Triggered by Thread: 0 Last Exception Backtrace: 0 CoreFoundation 0x11196e5f4 __exceptionPreprocess + 226 1 libobjc.A.dylib 0x11e8f5a45 objc_exception_throw + 48 2 libxamarin-dotnet-debug.dylib 0x10d3e4f6f xamarin_process_managed_exception + 943 3 libxamarin-dotnet-debug.dylib 0x10d3f1a42 xamarin_invoke_trampoline + 8578 4 libxamarin-dotnet-debug.dylib 0x10d3f90b9 xamarin_arch_trampoline + 105 5 libxamarin-dotnet-debug.dylib 0x10d3fa29e xamarin_x86_64_common_trampoline + 118 6 UIKitCore 0x12a048593 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 214 7 UIKitCore 0x12a04a284 -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:] + 4128 8 UIKitCore 0x12a04fc24 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1190 9 UIKitCore 0x1295c046a -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] + 122 10 UIKitCore 0x129bb4592 _UIScenePerformActionsWithLifecycleActionMask + 88 11 UIKitCore 0x1295c0f64 __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke + 198 12 UIKitCore 0x1295c09a1 -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] + 252 13 UIKitCore 0x1295c0d9a -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] + 831 14 UIKitCore 0x1295c0647 -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] + 354 15 UIKitCore 0x1295caa8f __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 178 16 UIKitCore 0x129a97b01 +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] + 859 17 UIKitCore 0x129bd1a19 _UISceneSettingsDiffActionPerformChangesWithTransitionContext + 246 18 UIKitCore 0x1295ca713 -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 346 19 UIKitCore 0x1293c7af5 __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke.578 + 796 20 UIKitCore 0x1293c64c7 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 253 21 UIKitCore 0x1293c76b5 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 255 22 UIKitCore 0x12a04e545 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 513 23 UIKitCore 0x129ac8afe -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 355 24 FrontBoardServices 0x12028bcdd -[FBSScene _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 415 25 FrontBoardServices 0x1202b8216 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke.180 + 102 26 FrontBoardServices 0x12029a0ef -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 209 27 FrontBoardServices 0x1202b7df5 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke + 352 28 libdispatch.dylib 0x11dacdb25 _dispatch_client_callout + 8 29 libdispatch.dylib 0x11dad0c9f _dispatch_block_invoke_direct + 281 30 FrontBoardServices 0x1202deda3 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30 31 FrontBoardServices 0x1202dec99 -[FBSSerialQueue _targetQueue_performNextIfPossible] + 174 32 FrontBoardServices 0x1202dedcb -[FBSSerialQueue _performNextFromRunLoopSource] + 19 33 CoreFoundation 0x1118db4a7 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 34 CoreFoundation 0x1118db39f __CFRunLoopDoSource0 + 180 35 CoreFoundation 0x1118da86c __CFRunLoopDoSources0 + 242 36 CoreFoundation 0x1118d4f68 __CFRunLoopRun + 871 37 CoreFoundation 0x1118d4704 CFRunLoopRunSpecific + 562 38 GraphicsServices 0x1207ccc8e GSEventRunModal + 139 39 UIKitCore 0x12a04c65a -[UIApplication _run] + 928 40 UIKitCore 0x12a0512b5 UIApplicationMain + 101 41 ??? 0x15bd78111 ??? 42 ??? 0x15bd75453 ??? 43 libmonosgen-2.0.dylib 0x10dab9fff mono_jit_runtime_invoke + 2223 44 libmonosgen-2.0.dylib 0x10d9dc318 mono_runtime_invoke_checked + 136 45 libmonosgen-2.0.dylib 0x10d9e30bb mono_runtime_exec_main_checked + 107 46 libmonosgen-2.0.dylib 0x10db1c0b2 mono_jit_exec + 354 47 libxamarin-dotnet-debug.dylib 0x10d3f8f0d xamarin_main + 1949 48 IosApp1 0x1044b1ac4 main + 52 (main.x86_64.mm:65) 49 dyld_sim 0x10cfccf21 start_sim + 10 50 dyld 0x20491251e start + 462 51 ??? 0x3 ??? Thread 0 Crashed:: tid_103 Dispatch queue: com.apple.main-thread 0I think this is similar to the issues reported in #12040 and #14796, but I'm not certain. Is there any workaround? If not, I don't think should wait for .NET 7.