Skip to content

Implement UnhandledException hook for finalizer scenario in Mono. - #118563

Merged
VSadov merged 11 commits into
dotnet:mainfrom
VSadov:unhMono
Aug 19, 2025
Merged

Implement UnhandledException hook for finalizer scenario in Mono.#118563
VSadov merged 11 commits into
dotnet:mainfrom
VSadov:unhMono

Conversation

@VSadov

Copy link
Copy Markdown
Member

A follow-up for #109806

Most of the implementation is in the shared corelib code and works for Mono, but finalization scenario needs special handling as that part is not shared.

@VSadovVSadov added the runtime-mono specific to the Mono runtime label Aug 10, 2025
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 10, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added linkable-framework Issues associated with delivering a linker friendly framework labels Aug 10, 2025
@VSadovVSadov added area-VM-meta-mono and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Aug 12, 2025
@VSadov
VSadov marked this pull request as ready for review August 13, 2025 01:54
CopilotAI review requested due to automatic review settings August 13, 2025 01:54

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements the UnhandledException hook for finalizer scenarios in Mono runtime, building on previous work in shared corelib code. The implementation ensures that unhandled exceptions in finalizers are properly handled through the global exception handler mechanism.

Key changes:

  • Introduces a new GuardedFinalize method that wraps finalizer calls with exception handling
  • Updates Mono's finalizer execution path to use the guarded version instead of direct finalizer calls
  • Enables previously excluded UnhandledException tests for Mono (with some exceptions)

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/tests/issues.targetsEnables UnhandledException tests for Mono, excluding only specific problematic test cases
src/mono/mono/mini/aot-compiler.cUpdates AOT compilation to use GuardedFinalize instead of Finalize for runtime-invoke
src/mono/mono/metadata/gc.cModifies finalizer execution to call GuardedFinalize and updates method resolution
src/mono/System.Private.CoreLib/src/System/Object.Mono.csImplements GuardedFinalize method with exception handling using UnsafeAccessor
src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xmlPreserves GuardedFinalize method from IL linking removal

Comment threadsrc/mono/System.Private.CoreLib/src/System/Object.Mono.cs Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@VSadov

Copy link
Copy Markdown
MemberAuthor

I think this is ready for a review.

There are some failures on ios/tvos, but I cannot tell if these are caused by the change.
In theory the approach should work on all platforms. - it seems to work even for WASM

@VSadov

Copy link
Copy Markdown
MemberAuthor

This keeps failing on ios/tvos. I am out of ideas why. @lambdageek - could you take a look?

Comment threadsrc/mono/System.Private.CoreLib/src/System/Object.Mono.cs Outdated
@lambdageek

lambdageek commented Aug 14, 2025

Copy link
Copy Markdown
Member

@VSadov I can't really see anything in the CI logs, but probably something needs to tell Mono's AOT compiler to compile GuardedFinalize

@kotlarmilos

Copy link
Copy Markdown
Member

Let me run it locally to try to get better diagnostics/ stack trace.

@kotlarmilos

Copy link
Copy Markdown
Member

I am getting the following error on iOS arm64 device:

((null) error) * Assertion at /Users/miloskotlar/dotnet/runtime-unsafe-accessor/src/mono/mono/metadata/gc.c:304, condition `is_ok (error)' not met, function:mono_gc_run_finalize, Attempting to JIT compile method '(wrapper runtime-invoke) object object:runtime_invoke_direct_void__this__ (object,intptr,intptr,intptr)' while running in aot-only mode. See https://learn.microsoft.com/xamarin/ios/internals/limitations for more information.

@VSadov

VSadov commented Aug 15, 2025

Copy link
Copy Markdown
MemberAuthor

I am getting the following error on iOS arm64 device:

((null) error) * Assertion at /Users/miloskotlar/dotnet/runtime-unsafe-accessor/src/mono/mono/metadata/gc.c:304, condition `is_ok (error)' not met, function:mono_gc_run_finalize, Attempting to JIT compile method '(wrapper runtime-invoke) object object:runtime_invoke_direct_void__this__ (object,intptr,intptr,intptr)' while running in aot-only mode. See https://learn.microsoft.com/xamarin/ios/internals/limitations for more information.

I think I am precompiling the wrapper. We had the same pattern before, just the wrapper was for Finalize and now it is for GuardedFinalize.
I wonder what is the difference?

The wrapper for Finalize was a virtual wrapper, since Finalize is a virtual method. The GuardedFinalize is not virtual, since it does not need to be.
I can make GuardedFinalize virtual and see what happens.

@VSadov

VSadov commented Aug 15, 2025

Copy link
Copy Markdown
MemberAuthor

Making GuardedFinalize virtual actually helps with ios/tvos. So it is not an issue with UnsafeAccessor. It is an issue with precompiling direct nonvirtual invoke wrapper.

Virtual GuardedFinalize could be ok, but less than ideal.
I will now try a nonvirtual again, but with non-direct wrapper.

Comment threadsrc/mono/mono/metadata/gc.c
@VSadov

VSadov commented Aug 18, 2025

Copy link
Copy Markdown
MemberAuthor

LLVMFULLAOT fails in Regression_2 JIT testcase. I do not think it is related.

The rest is passing now, including the newly enabled tests for UnhandledExceptionHandler - that is on all tested configs: JIT, interpreted, WASM or AOT/ios variants.

@VSadov

Copy link
Copy Markdown
MemberAuthor

/ba-g LLVMFULLAOT failure in Regression_2 is unrelated. Happens without this change as well (see: NOOP change in #118642)

@VSadov

Copy link
Copy Markdown
MemberAuthor

Thanks for reviewing!

@VSadov
VSadov merged commit de0650b into dotnet:mainAug 19, 2025
130 of 132 checks passed
@VSadov

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0-rc1

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0-rc1: https://github.com/dotnet/runtime/actions/runs/17064173533

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monolinkable-frameworkIssues associated with delivering a linker friendly frameworkruntime-monospecific to the Mono runtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@VSadov@lambdageek@vitek-karas@kotlarmilos