Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Mono.Android] Prevent NRE in VS Mac when breaking on exceptions (#7103)
Fixes: #7085 Fixes: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1554705 In a new Xamarin.Android project, if you go to your `OnCreate()` method and add a `throw new Exception("test")`, Visual Studio for Mac breaks on a `NullReferenceException` such as: [mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object. at Android.Runtime.JNINativeWrapper._unhandled_exception (System.Exception e) [0x0000e] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:12 at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V (_JniMarshal_PPL_V callback, System.IntPtr jnienv, System.IntPtr klazz, System.IntPtr p0) [0x0001d] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:111 at (wrapper native-to-managed) Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(intptr,intptr,intptr) This does not happen in VS Windows, only VS Mac. After reviewing my changes in 32cff43, the System.Reflection.Emit code path does a null check for `mono_unhandled_exception_method`: bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; if (filter && JNIEnv.mono_unhandled_exception_method != null) { ig.BeginExceptFilterBlock (); ig.Emit (OpCodes.Call, JNIEnv.mono_unhandled_exception_method); ig.Emit (OpCodes.Ldc_I4_1); ig.BeginCatchBlock (null!); } else { ig.BeginCatchBlock (typeof (Exception)); } While the new "fast" code path, does not: static bool _unhandled_exception (Exception e) { if (Debugger.IsAttached || !JNIEnv.PropagateExceptions) { JNIEnv.mono_unhandled_exception (e); return false; } return true; } Adding `JNIEnv.mono_unhandled_exception?.Invoke(e)` appears to solve the problem when I build a local copy of `Mono.Android.dll` and test it inside VS Mac. I see my exception break properly on the line I threw the exception. `mono_unhandled_exception` being null appears to be something introduced in 2aff4e7. That commit's goal was to not lookup `mono_unhandled_exception_method` at startup, but wait until an exception is thrown. Unfortunately, `mono_unhandled_exception_method` is null at the time that the code S.R.Emitted, so we've had this behavior for a while! Since we are looking at reworking this entire system with "marshal methods" as in #7004, I think we should simply add the null check for now. We should probably investigate the sequence of events during startup & unhandled exceptions when the new system is in place.
- Loading branch information