Skip to content

Conversation

@grendello
Copy link
Contributor

…public

Fixes: #10602
Context: 8bc7a3e

This is in the category of "how the hell has it worked before?", as every time the AndroidEnvironmentInternal.UnhandledException method living in Mono.Android.Runtime.dll would be called, the runtime would respond with a method not accessible exception, rightly so as both the type and the method were internal and visible only to Mono.Android.dll.

I guess we haven't had many unhandled exceptions in marshal method wrappers over the years?

This PR fixes the problem by making both the type and the method public. This is the simplest way to fix the issue.

Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

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

Can we write some Mono.Cecil code to make this public at build time? So, no one can use it at C# compile time?

This would happen in the marshal methods MSBuild steps, if they run.

@grendello grendello marked this pull request as draft November 24, 2025 15:00
@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch 2 times, most recently from 826cf5b to c4df398 Compare November 26, 2025 09:01
@grendello grendello marked this pull request as ready for review November 26, 2025 09:01
@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch from c4df398 to 09e3968 Compare December 5, 2025 08:25
@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch from 09e3968 to ac87126 Compare December 12, 2025 09:54
@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch from ac87126 to 02eea78 Compare January 9, 2026 11:55
@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch 2 times, most recently from aa667db to f601380 Compare January 30, 2026 09:59
static void CopyFile (TaskLoggingHelper log, string source, string target)
{
log.LogDebugMessage ($"Copying rewritten assembly: {source} -> {target}");
MonoAndroidHelper.CopyFileAvoidSharingViolations (log, source, target);
Copy link
Member

Choose a reason for hiding this comment

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

Did you find you needed this before this PR was green?

Is it because the .dll files are still open, such as here:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it would hit the sharing violation exception from time to time. It might be due to the code you pointed to, but fixing this should be done in a separate PR.

Copy link

Copilot AI left a comment

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 fixes issue #10602 where marshal method wrappers crash with a MethodAccessException when trying to call AndroidEnvironmentInternal.UnhandledException. The method and its containing type were internal, making them inaccessible from generated marshal method wrapper code.

Changes:

  • Makes the UnhandledException method public in the source code
  • Adds a new MSBuild task that modifies the Mono.Android.Runtime.dll assembly at build time to make the AndroidEnvironmentInternal type public
  • Refactors file handling utilities in MarshalMethodsAssemblyRewriter to reusable helper methods

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/Mono.Android.Runtime/Android.Runtime/AndroidEnvironmentInternal.cs Makes the UnhandledException method public (class remains internal in source)
src/Xamarin.Android.Build.Tasks/Tasks/FixUpMonoAndroidRuntime.cs New MSBuild task that identifies Mono.Android.Runtime.dll and applies the fixup
src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidRuntimeMarshalMethodsFixUp.cs New utility that uses Mono.Cecil to modify the assembly and make AndroidEnvironmentInternal type public
src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs Adds reusable file copy and delete helper methods
src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.cs Refactored to use the new helper methods for file operations
src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets Registers and invokes the new FixUpMonoAndroidRuntime task before RewriteMarshalMethods
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs Adds test to verify the type becomes public after the fixup

…public

Fixes: #10602
Context: 8bc7a3e

This is in the category of "how the hell has it worked before?", as every time the
`AndroidEnvironmentInternal.UnhandledException` method living in `Mono.Android.Runtime.dll`
would be called, the runtime would respond with a method not accessible exception, rightly
so as both the type and the method were internal and visible only to `Mono.Android.dll`.

I guess we haven't had many unhandled exceptions in marshal method wrappers over the years?

This PR fixes the problem by making both the type and the method public. This is the simplest
way to fix the issue.
The rewrite changes visibility of the `Android.Runtime.AndroidEnvironmentInternal` type
from `internal` to `public` after all the linking and marshal method processing is done.
@grendello grendello force-pushed the dev/grendel/mm-unhandledexception branch from f601380 to 3f001b3 Compare February 2, 2026 17:22
@jonathanpeppers
Copy link
Member

@grendello today I learned about [assembly: IgnoresAccessChecksToAttribute ("Mono.Android")]:

This appears to be a runtime feature, that Mono even implements? I can't find docs on it, though.

Can we simply stamp this attribute on every assembly? It could probably be done in the existing MSBuild tasks that write the marshal methods?

@grendello
Copy link
Contributor Author

@grendello today I learned about [assembly: IgnoresAccessChecksToAttribute ("Mono.Android")]:

* https://github.com/search?q=repo%3Adotnet%2Fruntime+IgnoresAccessChecksToAttribute&type=code

This appears to be a runtime feature, that Mono even implements? I can't find docs on it, though.

Yeah, it appears to be undocumented which has me worried a bit. Mono does have support for it in https://github.com/dotnet/runtime/blob/0bbe2a937db7b916ca94849de3a3d16f23f8b17f/src/mono/mono/metadata/assembly.c#L1707-L1710

The comment there appears to suggest it might be meant only for dynamically generated modules?

Can we simply stamp this attribute on every assembly? It could probably be done in the existing MSBuild tasks that write the marshal methods?

TBH, there's too much uncertainty about this attribute and its role. I wouldn't feel comfortable using it. It also appears to be a nuclear solution to the problem - it would essentially let anyone access anything in our assemblies, thus potentially creating maintenance problems for the future (people could start relying on internals being there because of that attribute)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crashes with Method Android.Runtime.AndroidEnvironmentInternal.UnhandledException(System.Exception) is inaccessible (...) exception

2 participants