Open jakobbotsch opened 11 months ago
By analysing the provided CI build and reproducing locally this seems to only fail in full AOT mode.
The tests passes on: osx-x64 Release AllSubsets_Mono_Minijit_RuntimeTests minijit
https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-90318-merge-cedc27ee86b44aab89/Regression_2/1/Regression_2.testResults.xml.txt?helixlogtype=result
<test name="JIT/Regression/JitBlue/Runtime_90219/Runtime_90219/Runtime_90219.dll" type="Runtime_90219" method="TestEntryPoint" time="0.004416" result="Pass"></test>
The crash seems to be related to using custom AssemblyLoadContext
in fullAOT mode with Mono, which doesn't seem to initialize static members of the reflected type properly. Using the default ALC AssemblyLoadContext.Default
works properly.
A smaller repro:
using System;
using System.Reflection;
using System.Runtime.Loader;
namespace HelloWorld
{
public class CustomAssemblyLoadContext : AssemblyLoadContext
{
public CustomAssemblyLoadContext(): base(true)
{
}
}
internal class Program
{
private static void Main(string[] args)
{
// This does not crash when we use AssemblyLoadContext.Default
var customAlc = new CustomAssemblyLoadContext();
Test(customAlc);
}
public static void Test(AssemblyLoadContext alc)
{
var asm = alc.LoadFromAssemblyPath(System.Reflection.Assembly.GetExecutingAssembly().Location);
var mi = asm.GetType(typeof(Program).FullName).GetMethod(nameof(MyMethod));
var pass = (bool)mi.Invoke(null, null);
if (pass)
Console.WriteLine("pass");
else
Console.WriteLine("fail");
}
public static byte TheByte = 42;
public static bool MyMethod()
{
var aByte = TheByte;
Console.WriteLine($"aByte: {aByte}");
return (int) aByte == 42;
}
}
}
Running the above in full AOT mode prints:
aByte: 0
fail
@vargaz do we support loading AOT images for assemblies from non-default ALC?
It's a collectible ALC. So it looks like we reall dont' support it.
I think that Invoke
should throw something instead of allowing the method to execute somehow
Update but on the other hand, we apparently turn all ALCs into non-collectible ALCs??
I think load_image
in aot-runtime.c shouldn't use mono_alc_get_ambient()
which always just returns mono_alc_get_default()
. It should use the ALC of the AOT image's module.
because in decode_klass_ref
we do this:
case MONO_AOT_TYPEREF_TYPEDEF_INDEX:
idx = decode_value (p, &p);
image = load_image (module, 0, error);
if (!image)
return NULL;
klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, error);
break;
case MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE:
idx = decode_value (p, &p);
image = load_image (module, decode_value (p, &p), error);
if (!image)
return NULL;
klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF + idx, error);
break;
so we always end up with a reference to the MonoClass*
from the default ALC. So I bet when we go to initialize static fields, we share the runtime vtable of the default ALC
The test being added in #90318 fails on Mono in full AOT mode:
https://dev.azure.com/dnceng-public/public/_build/results?buildId=370197&view=ms.vss-test-web.build-test-results-tab&runId=7857242&paneView=debug