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

Failed to create proxy when inside an AssemblyLoadContext in net6 #26

Open
cc004 opened this issue Jun 15, 2022 · 2 comments
Open

Failed to create proxy when inside an AssemblyLoadContext in net6 #26

cc004 opened this issue Jun 15, 2022 · 2 comments

Comments

@cc004
Copy link

cc004 commented Jun 15, 2022

stacktrace

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.FileLoadException: Could not load file or assembly 'MonoMod.Common, Version=22.3.5.1, Culture=neutral, PublicKeyToken=null'. Operation is not supported. (0x80131515)
File name: 'MonoMod.Common, Version=22.3.5.1, Culture=neutral, PublicKeyToken=null'
 ---> System.NotSupportedException: Resolving to a collectible assembly is not supported.
   at System.Reflection.RuntimeAssembly.GetType(QCallAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at System.Reflection.Assembly.GetType(String name)
   at MonoMod.Utils.Cil.ILGeneratorShim.ILGeneratorBuilder.GenerateProxy()
   at MonoMod.Utils.Cil.ILGeneratorShim.GetProxy()
   at HarmonyLib.MethodPatcher..ctor(MethodBase original, MethodBase source, List`1 prefixes, List`1 postfixes, List`1 transpilers, List`1 finalizers, Boolean debug)
   at HarmonyLib.PatchFunctions.UpdateWrapper(MethodBase original, PatchInfo patchInfo)
   at HarmonyLib.PatchProcessor.Patch()
   at Localizer.Utils.Patch(Harmony instance, String class, String method, Boolean exactMatch, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod transpiler) in Localizer\Helpers\Utils.cs:line 426
   at Localizer.Localizer..ctor() in Localizer.cs:line 59
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   --- End of inner exception stack trace ---
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   at Terraria.ModLoader.Core.AssemblyManager.Instantiate(ModLoadContext mod) in tModLoader\Terraria\ModLoader\Core\AssemblyManager.cs:line 188
   at Terraria.ModLoader.Core.AssemblyManager.<>c__DisplayClass11_0.<InstantiateMods>b__1(ModLoadContext mod) in tModLoader\Terraria\ModLoader\Core\AssemblyManager.cs:line 260
   at System.Linq.Enumerable.SelectListIterator`2.ToList()
   at Terraria.ModLoader.Core.AssemblyManager.InstantiateMods(List`1 modsToLoad, CancellationToken token) in tModLoader\Terraria\ModLoader\Core\AssemblyManager.cs:line 258
   at Terraria.ModLoader.Core.ModOrganizer.LoadMods(CancellationToken token) in tModLoader\Terraria\ModLoader\Core\ModOrganizer.cs:line 243
   at Terraria.ModLoader.ModLoader.Load(CancellationToken token) in tModLoader\Terraria\ModLoader\ModLoader.cs:line 116
@CyberAndrii
Copy link

This happens when assembly MonoMod.Utils is loaded in a collectible AssemblyLoadContext which prevents the non-collectible MonoMod.Utils.Cil.ILGeneratorProxy to be loaded.

Potential fix is to load MonoMod.Utils.Cil.ILGeneratorProxy in the same AssemblyLoadContext as MonoMod.Utils. This line should look like this (simplified, in reality we will need to use reflection on older target frameworks):

var utilsAssembly = Assembly.GetExecutingAssembly();
var context = AssemblyLoadContext.GetLoadContext(utilsAssembly);
asm = context.LoadFromStream(copy);

Without this fix it is a bug which got patched in the .NET Runtime 7 and now throws the exception OP posted.

@nike4613
Copy link
Contributor

I'm honestly not sure supporting MonoMod being loaded in a collectible ALC is a good idea. In fact, I'm fairly certain that it is a terrible idea. MonoMod relies on being able to root objects in statics, and must be able to keep detours alive and correct. If the runtime were to unload it, that could (in fact, would) leave detours in invalid states and be liable to inducing runtime crashes.

If we did want to support it, the only safe support we can have is allocating a GC handle to some MonoMod object as long as there are references in the DynamicReferenceManager. This should effectively root all relevant MonoMod types, preventing them from being collected. This does also defeat the purpose of unloadable ALCs though.


I do think it's a good idea to load our dynamically generated assemblies in the same ALC that created them though. That would require some more work than just the proposed change however.

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

No branches or pull requests

3 participants