-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[mono][System.Reflection.Emit] VTable initialization failure for class implementing an interface #94490
Comments
This is making aspnetcore tests fail with net8.0 when Mono is used as the runtime. See #94437 (comment) |
/cc @SamMonoRT |
Oh I bet I know what it is. I bet something goes wrong when this Although I'm not sure how we actually end up seeing a generic param there. Running with |
It's not really a vtable problem. It's some problem with the IL generation in |
Ok, really it has to do with Apparently if you use methodBuilder = typeBuidler.DefineMethod(methodName, methodAttributes);
methodBuilder.SetReturnType(returnType);
methodBuilder.SetParameters(paramTypes); the code works. The problem is that if you use the longer version with Simple repro: public interface IStr
{
public string MStr(string x);
}
public class P {
public static void Main()
{
var aname = "TestAssembly";
var assemblyName = new AssemblyName(aname);
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(aname);
var typeBuilder = moduleBuilder.DefineType("TestType", TypeAttributes.Public, typeof(object), new Type[] { typeof(IStr) });
#if false
//works
var methodBuilder = typeBuilder.DefineMethod("MStr", MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), new Type[] { typeof(string) });
#else
// throws "Invalid VTable" from CreateInstance, below
var methodBuilder = typeBuilder.DefineMethod("MStr", MethodAttributes.Public | MethodAttributes.Virtual);
methodBuilder.SetReturnType(typeof(string));
methodBuilder.SetParameters(new Type[] { typeof(string) });
#endif
var ilg = methodBuilder.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
var obj = Activator.CreateInstance(type);
var m = type.GetMethod("MStr");
var r = m.Invoke(obj, new object[] { "hello" });
Console.WriteLine($"r = {r}");
}
} |
@tmds @uweigand @janani66 consider patching aspnetcore here: to replace var methodBuilder = type.DefineMethod(interfaceMethodInfo.Name, methodAttributes);
...
methodBuilder.SetReturnType(interfaceMethodInfo.ReturnType);
methodBuilder.SetParameters(paramTypes); by var methodBuilder = type.DefineMethod(interfaceMethodInfo.Name, methodAttributes, interfaceMethodInfo.ReturnType, paramTypes);
... |
@lambdageek Test Run Results: |
@lambdageek will this issue be fixed on the short term? If not, it would be good to include your workaround directly in aspnetcore so SignalR gets fixed for everyone doing Mono based .NET builds. |
@tmds I think the fix will probably miss the first couple of servicing releases for .NET 8 due to winter holidays and scheduling. That said, here's what I think needs to be fixed @ivanpovazan @buyaa-n Compare runtime/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs Lines 624 to 633 in 8ebe003
and Mono: runtime/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.Mono.cs Lines 595 to 606 in 8ebe003
I think Mono should do: if (returnType != null)
rtype = returnType;
runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs Lines 77 to 89 in 8ebe003
|
Reopening until the backport is not merged: |
@ivanpovazan the backport PR was approved by tactics so you can merge it |
Thanks @akoeplinger! Closing as the backport has also been merged. |
When using System.Reflection.Emit with Mono, using
MethodBuilder.SetReturnType
andMethodBuilder.SetParameters
on methods that are supposed to implement interface methods does not work - the method is not considered to implement the interface method. Using the long form ofTypeBuilder.DefineMethod
works.Update simpler repro and better diagnosis; original issue below
Needs some investigation still. Some of the System.Reflection.Emit code generates a class with a bad vtable on net8.0.
The TypedClientBuilder is from aspnetcore:
https://github.com/dotnet/aspnetcore/blob/556f39af49b1a32f14089d3809557825932e4ca5/src/SignalR/server/Core/src/Internal/TypedClientBuilder.cs#L49
Repro:
Clone this repo https://github.com/lambdageek/repro-iclientproxy-vtable-fail
Expected
Actual
The text was updated successfully, but these errors were encountered: