From 7a43706240cf674e31d6bd6a8eac8f7d286efcb4 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 23 Jul 2021 10:15:33 -0500 Subject: [PATCH 1/6] [tests] enable SubscribeToAppDomainUnhandledException in .NET 6 Context: c1a2ee70 Context: https://github.com/dotnet/runtime/issues/44526 If c1a2ee70 is working now, we should be able to enable this test. --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 6340c5ec679..af781f6cb7e 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -60,7 +60,6 @@ void Button_ViewTreeObserver_GlobalLayout (object sender, EventArgs e) } [Test] - [Category ("DotNetIgnore")] // TODO: UnhandledException not firing: https://github.com/dotnet/runtime/issues/44526 public void SubscribeToAppDomainUnhandledException () { AssertHasDevices (); From 87849beca9ffe0aee712446e9be78957cf4f53c1 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 26 Jul 2021 18:34:19 -0400 Subject: [PATCH 2/6] Only notify debugger if debugger is attached Context: https://github.com/dotnet/runtime/issues/44526#issuecomment-886998881 Context: https://github.com/dotnet/runtime/issues/44526#issuecomment-887052471 Context: start: https://discord.com/channels/732297728826277939/732297837953679412/869330822262587392 Context: end? https://discord.com/channels/732297728826277939/732297837953679412/869343082552893440 On .NET 6, `JNIEnv.mono_unhandled_exception` is `monodroid_debugger_unhandled_exception()`, which calls `mono_debugger_agent_unhandled_exception()`; see also e4debf72. The problem is that in our current world order of "Mono components" (0f7a0cde), if the debugger isn't used, then we get "debugger stubs" for the mono debugger agent, which turns `mono_debugger_agent_unhandled_exception()` into an [*assertion*][0]: static void stub_debugger_unhandled_exception (MonoException *exc) { g_assert_not_reached (); } The result is that when an exception is thrown, *before* the `AppDomain.UnhandledException` event can be raised, the runtime dies in a horrible flaming assertion death: E andledexceptio: * Assertion: should not be reached at /__w/1/s/src/mono/mono/component/debugger-stub.c:175 Avoid this issue by checking `Debugger.IsAttached` *before* calling `monodroid_debugger_unhandled_exception()`. Additionally, remove some obsolete comments: .NET 6 couldn't resolve `Debugger.Mono_UnhandledException()` because .NET 6 never had it, so the linker was right to warn about its absence. [0]: https://github.com/dotnet/runtime/blob/16b456426dfb5212a24bfb78bfd5d9adfcc95185/src/mono/mono/component/debugger-stub.c#L172-L176 --- src/Mono.Android/Android.Runtime/JNIEnv.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs index 6cdd1545626..f720fab843e 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnv.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs @@ -294,9 +294,9 @@ internal static void PropagateUncaughtException (IntPtr env, IntPtr javaThreadPt var javaException = JavaObject.GetObject (env, javaExceptionPtr, JniHandleOwnership.DoNotTransfer)!; - // Disabled until Linker error surfaced in https://github.com/xamarin/xamarin-android/pull/4302#issuecomment-596400025 is resolved - //System.Diagnostics.Debugger.Mono_UnhandledException (javaException); - mono_unhandled_exception?.Invoke (javaException); + if (Debugger.IsAttached) { + mono_unhandled_exception?.Invoke (javaException); + } try { var jltp = javaException as JavaProxyThrowable; From c37f58a17c0d0fa7a06955c1fabc8b9ac3a8c0f8 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 10 Aug 2021 16:35:13 -0400 Subject: [PATCH 3/6] Fix tests? Context: https://github.com/xamarin/xamarin-android/pull/6119#issuecomment-896246633 Looks like under .NET 6, `Console.WriteLine(s)` output isn't guaranteed to be on a single (assuming `s` doesn't contain a newline). This causes the existing `SubscribeToAppDomainUnhandledException()` check to fail, because while it *wants* # Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH! it's *actually* getting: # Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception : CRASH! Try to "add magic" around the line check so that expected output can span multiple lines. Let's see if that fixes things. --- .../Tests/InstallAndRunTests.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index af781f6cb7e..51bb849f9a3 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -84,9 +84,34 @@ public void SubscribeToAppDomainUnhandledException () AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); string expectedLogcatOutput = "# Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; - Assert.IsTrue (MonitorAdbLogcat ((line) => { - return line.Contains (expectedLogcatOutput); - }, Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), 60), $"Output did not contain {expectedLogcatOutput}!"); + Assert.IsTrue ( + MonitorAdbLogcat (CreateLineChecker (expectedLogcatOutput), + logcatFilePath: Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), timeout: 60), + $"Output did not contain {expectedLogcatOutput}!"); + } + + static Func CreateLineChecker (string expectedLogcatOutput) + { + // On .NET 6, `adb logcat` output may be line-wrapped in unexpected ways. + // https://github.com/xamarin/xamarin-android/pull/6119#issuecomment-896246633 + // Try to see if *successive* lines match expected output + int startIndex = 0; + return line => { + int count = expectedLogcatOutput.Length - startIndex; + if (line.IndexOf (expectedLogcatOutput, startIndex, count) >= 0) { + return true; + } + while (--count > 0) { + if (line.IndexOf (expectedLogcatOutput, startIndex, count) >= 0) { + TestContext.Out.WriteLine ($"# jonp: found partial line match! `{expectedLogcatOutput.Substring (startIndex, count)}`"); + startIndex += count; + TestContext.Out.WriteLine ($"# jonp: next, looking for: `{expectedLogcatOutput.Substring (startIndex)}`"); + return false; + } + } + startIndex = 0; + return false; + }; } Regex ObfuscatedStackRegex = new Regex ("in <.*>:0", RegexOptions.Compiled); From 5622966331e8b336c98de1338886d2b791b12e8a Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 11 Aug 2021 15:30:51 -0400 Subject: [PATCH 4/6] Fix CreateLineChecker() --- .../Tests/InstallAndRunTests.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 51bb849f9a3..9c6aeda9035 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -90,28 +90,34 @@ public void SubscribeToAppDomainUnhandledException () $"Output did not contain {expectedLogcatOutput}!"); } - static Func CreateLineChecker (string expectedLogcatOutput) + + public static Func CreateLineChecker (string expectedLogcatOutput) { // On .NET 6, `adb logcat` output may be line-wrapped in unexpected ways. // https://github.com/xamarin/xamarin-android/pull/6119#issuecomment-896246633 // Try to see if *successive* lines match expected output - int startIndex = 0; + var remaining = expectedLogcatOutput; return line => { - int count = expectedLogcatOutput.Length - startIndex; - if (line.IndexOf (expectedLogcatOutput, startIndex, count) >= 0) { + if (line.IndexOf (remaining) >= 0) { + Reset (); return true; } - while (--count > 0) { - if (line.IndexOf (expectedLogcatOutput, startIndex, count) >= 0) { - TestContext.Out.WriteLine ($"# jonp: found partial line match! `{expectedLogcatOutput.Substring (startIndex, count)}`"); - startIndex += count; - TestContext.Out.WriteLine ($"# jonp: next, looking for: `{expectedLogcatOutput.Substring (startIndex)}`"); + int count = Math.Min (line.Length, remaining.Length); + for ( ; count > 0; count--) { + var startMatch = remaining.Substring (0, count); + if (line.IndexOf (startMatch) >= 0) { + remaining = remaining.Substring (count); return false; } } - startIndex = 0; + Reset (); return false; }; + + void Reset () + { + remaining = expectedLogcatOutput; + } } Regex ObfuscatedStackRegex = new Regex ("in <.*>:0", RegexOptions.Compiled); From 74d32cb0f6be7a60900abf6e57c344d079a01317 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 11 Aug 2021 21:16:59 -0400 Subject: [PATCH 5/6] Updated expected output for net6. --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 9c6aeda9035..320dd229b0e 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -83,7 +83,11 @@ public void SubscribeToAppDomainUnhandledException () else AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); +#if NETCOREAPP string expectedLogcatOutput = "# Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; +#else // NETCOREAPP + string expectedLogcatOutput = "# Unhandled Exception: sender=System.Object; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; +#endif // NETCOREAPP Assert.IsTrue ( MonitorAdbLogcat (CreateLineChecker (expectedLogcatOutput), logcatFilePath: Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), timeout: 60), From feafb6ca43fb41b06241d0a808f559d907f0de80 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 12 Aug 2021 06:42:59 -0400 Subject: [PATCH 6/6] Doh! got the #if backwards! --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 320dd229b0e..8fdc8562fd3 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -84,9 +84,9 @@ public void SubscribeToAppDomainUnhandledException () AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity"); #if NETCOREAPP - string expectedLogcatOutput = "# Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; -#else // NETCOREAPP string expectedLogcatOutput = "# Unhandled Exception: sender=System.Object; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; +#else // NETCOREAPP + string expectedLogcatOutput = "# Unhandled Exception: sender=RootDomain; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH"; #endif // NETCOREAPP Assert.IsTrue ( MonitorAdbLogcat (CreateLineChecker (expectedLogcatOutput),