Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime_90219 fails on Mono #90374

Open
jakobbotsch opened this issue Aug 11, 2023 · 5 comments
Open

Runtime_90219 fails on Mono #90374

jakobbotsch opened this issue Aug 11, 2023 · 5 comments
Assignees
Labels
area-Codegen-AOT-mono disabled-test The test is disabled in source code against the issue
Milestone

Comments

@jakobbotsch
Copy link
Member

jakobbotsch commented Aug 11, 2023

The test being added in #90318 fails on Mono in full AOT mode:

22:14:29.962 Running test: JIT/Regression/JitBlue/Runtime_90219/Runtime_90219/Runtime_90219.dll
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.NullReferenceException: Object reference not set to an instance of an object
   at Runtime_90219.MainInner(IRuntime rt)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Runtime_90219.TestEntryPoint()
   at Program.<<Main>$>g__TestExecutor335|0_336(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0& )

https://dev.azure.com/dnceng-public/public/_build/results?buildId=370197&view=ms.vss-test-web.build-test-results-tab&runId=7857242&paneView=debug

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 11, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Aug 11, 2023
@jakobbotsch jakobbotsch added area-Codegen-meta-mono and removed untriaged New issue has not been triaged by the area owner labels Aug 11, 2023
@vcsjones vcsjones removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 11, 2023
@SamMonoRT SamMonoRT added the disabled-test The test is disabled in source code against the issue label Aug 11, 2023
@SamMonoRT SamMonoRT added this to the 9.0.0 milestone Aug 11, 2023
@ivanpovazan
Copy link
Member

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>

@ivanpovazan
Copy link
Member

ivanpovazan commented Aug 16, 2023

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

@ivanpovazan
Copy link
Member

@vargaz do we support loading AOT images for assemblies from non-default ALC?

@lambdageek
Copy link
Member

lambdageek commented Aug 18, 2023

It's a collectible ALC. So it looks like we reall dont' support it.

if (mono_image_get_alc (assembly->image)->collectible)
/*
* Assemblies loaded into collectible ALCs require different codegen
* due to static variable access etc.
*/
return;

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??

@lambdageek
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Codegen-AOT-mono disabled-test The test is disabled in source code against the issue
Projects
None yet
Development

No branches or pull requests

5 participants