Skip to content

[CoreCLR] Propagate unhandled exceptions #10654

@simonrozsival

Description

@simonrozsival

Android framework version

net10.0-android (Preview)

Affected platform version

.NET 10

Description

Uncaught exceptions crash the app and don't raise the AppDomain.CurrentDomain.UnhandledException event. This is an API that's relied on by crash reporting tools.

Steps to Reproduce

  1. Add the following snippet somewhere into a new project:
AppDomain.CurrentDomain.UnhandledException += (sender, e)
{
    Console.WriteLine($"UnhandledException: {e.ExceptionObject}");
};

throw new Exception("testing");

With Mono, the UnhandledException: log will be produced, with CoreCLR it won't.

My current best understanding is that we fail to propagate the managed exception across .NET/Java boundary:

static AndroidRuntimeInternal ()
{
if (RuntimeFeature.IsMonoRuntime) {
mono_unhandled_exception = MonoUnhandledException;
} else if (RuntimeFeature.IsCoreClrRuntime) {
mono_unhandled_exception = CoreClrUnhandledException;
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}
}
static void CoreClrUnhandledException (Exception ex)
{
// TODO: Is this even needed on CoreCLR?
}
// Needed when running under CoreCLR, which doesn't allow icalls/ecalls. Any method which contains any reference to
// an unregistered icall/ecall method will fail to JIT (even if the method isn't actually called). In this instance
// it affected the static constructor which tried to assign `RuntimeNativeMethods.monodroid_debugger_unhandled_exception`
// to `mono_unhandled_exception` at the top of the class.
static void MonoUnhandledException (Exception ex)
{
RuntimeNativeMethods.monodroid_debugger_unhandled_exception (ex);
}

... but it's possible the problem is somewhere else completely.

The InstallAndRunTests.SubscribeToAppDomainUnhandledException is currently disabled for CoreCLR because of this:

// TODO: check if AppDomain.CurrentDomain.UnhandledException even works in CoreCLR
[Test]
public void SubscribeToAppDomainUnhandledException ([Values (AndroidRuntime.MonoVM, AndroidRuntime.CoreCLR)] AndroidRuntime runtime)
{
if (runtime == AndroidRuntime.CoreCLR) {
Assert.Ignore ("AppDomain.CurrentDomain.UnhandledException doesn't work in CoreCLR");
return;
}
proj = new XamarinAndroidApplicationProject () {
IsRelease = true,
};
proj.SetRuntime (runtime);
if (runtime == AndroidRuntime.MonoVM) {
proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
} else {
proj.SetRuntimeIdentifiers (new [] {"arm64-v8a", "x86_64"});
}
proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}",
@" AppDomain.CurrentDomain.UnhandledException += (sender, e) => {
Console.WriteLine (""# Unhandled Exception: sender={0}; e.IsTerminating={1}; e.ExceptionObject={2}"",
sender, e.IsTerminating, e.ExceptionObject);
};
throw new Exception (""CRASH"");
");
builder = CreateApkBuilder ();
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");
RunProjectAndAssert (proj, builder);
string expectedLogcatOutput = "# Unhandled Exception: sender=System.Object; e.IsTerminating=True; e.ExceptionObject=System.Exception: CRASH";
Assert.IsTrue (
MonitorAdbLogcat (CreateLineChecker (expectedLogcatOutput),
logcatFilePath: Path.Combine (Root, builder.ProjectDirectory, "startup-logcat.log"), timeout: 60),
$"Output did not contain {expectedLogcatOutput}!");
}

Did you find any workaround?

No response

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: CoreCLRIssues that only occur when using CoreCLR.bugComponent does not function as intended.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions