citizenfx / fivem

The source code for the Cfx.re modification frameworks, such as FiveM, RedM and LibertyM, as well as FXServer.
https://cfx.re/
3.57k stars 2.11k forks source link

C#: Cannot use in parameter with generic method override on Linux #1554

Open impulsh opened 2 years ago

impulsh commented 2 years ago

An exception is thrown when overriding a generic class method with an in parameter. This works fine on a Windows client and server, but the same code on a Linux server fails loading the assembly. Tested with build 5777.

I'm not sure what version of Mono is used - or how easy it would be to cherry-pick some commits if need be, but I've come across https://github.com/mono/mono/issues/10834 and believe this is the same issue, with https://github.com/mono/mono/pull/12802 being the fix.

Minimal repro:

using CitizenFX.Core;

namespace Test
{
    public abstract class MyGenericClass<T>
    {
        public abstract void MyMethod(in T value);
    }

    public class MyDerivedClass<T> : MyGenericClass<T>
    {
        public override void MyMethod(in T value)
        {
            Debug.WriteLine(value.ToString());
        }
    }

    public class TestScript : BaseScript
    {
        public TestScript()
        {
            MyDerivedClass<Vector3> test = new MyDerivedClass<Vector3>();
            test.MyMethod(Vector3.Zero);
        }
    }
}

Exception thrown:

Failed to instantiate instance of script Test.TestScript: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
  ---> System.TypeLoadException: Could not find method '.ctor' due to a type load error: Type Test.MyDerivedClass`1[T] has invalid vtable method slot 4 with method none assembly:data-0x7fb6516fdda0 type:MyDerivedClass`1 member:(null)
  at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke(System.Reflection.MonoCMethod,object,object[],System.Exception&)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00005] in <9391d7651e69459eae268d8a1dfa670f>:0
   --- End of inner exception stack trace ---
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00017] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) [0x000a8] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.RuntimeType.CreateInstanceSlow (System.Boolean publicOnly, System.Boolean wrapExceptions, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) [0x00009] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.RuntimeType.CreateInstanceDefaultCtor (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Boolean wrapExceptions, System.Threading.StackCrawlMark& stackMark) [0x00027] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00020] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic) [0x00000] in <9391d7651e69459eae268d8a1dfa670f>:0
  at System.Activator.CreateInstance (System.Type type) [0x00000] in <9391d7651e69459eae268d8a1dfa670f>:0
  at CitizenFX.Core.InternalManager.CreateAssemblyInternal (System.String assemblyFile, System.Byte[] assemblyData, System.Byte[] symbolData) [0x0007b] in /src/code/client/clrcore/InternalManager.cs:156
blattersturm commented 2 years ago

Mono version used on both server builds should be equivalent, but see the caveats below as Windows was built from main and Linux was built from patched tags, which diverged at the time.

No such commit has been cherry-picked in anywhere, but it may be Linux is on 5.16 and Windows is on 5.18 as 5.18 and higher on Linux had a weird memory corruption bug (around d1ec7d4459a33e6d4828f94ba9105f96c17f2876 timeframe?), or they may be on different sub-releases.

I'm unable to check this right now or any time soon as the Linux package build trees are on some disconnected SSD or disk image of an old SSD or whatever and I'm not going to dig through this for a minor inconsequential issue that's easy to work around, but FWIW the Windows build seemed to be on mono/mono@ed0d0554242805864a67013932ccaaf029fe5455, or this was an attempt at updating it that never went anywhere and therefore the current tree is lost to time as of a tweak around 76a29196e598c3b2426270070f5c3e1266a63900 and apparently that means the Windows bundle did get updated and wasn't reverted when 62e1a145e57de92111a9001079555ab20160ca27 got reverted in 784088f5f42c7cc554e5c5502eb298da4ee0237c... or it's which is the same version since e649e9c1d894338cb93cf493399710a4620689b6 as that matches the Mono commit's timeframe and Mono's branch model was a bit weird so even though that commit first showed in '6.4' tags, the 5.x branches were seeing a different baseline.

Either way, I'm not sure where the Linux trees went anyway and newer tags had weird memory corruption issues so this can't be acted upon at this time.

Since people also seem to be bumping this issue to be 'looked at' in roundabout ways, which is the only reason I looked into this at all, and I can't deal with that right now (or the emoji responses, really? if you have something to add, use words, or don't add anything), I'll lock this issue.