Closed Nemo-G closed 7 months ago
Does the app have some kind of c# assembly loader callback installed ?
@vargaz I think not, the app is quite simple. What exact function or keyword shall I search for a loader cb? BTW here is a more detailed callstack
And I tried to generate DOTween.Modules.dll
and once it is found everything works fine.
The caller looks like
Type looseScriptType = DOTweenUtils.GetLooseScriptType("DG.Tweening.DOTweenModuleUtils");
if (looseScriptType == null)
Debugger.LogError((object) "Couldn't load Modules system");
else
looseScriptType.GetMethod("Init", BindingFlags.Static | BindingFlags.Public).Invoke((object) null, (object[]) null);
The runtime calls AssemblyLoadContext.OnAssemblyResolve when it cannot find an assembly, which looks like this:
// This method is called by the VM.
private static RuntimeAssembly? OnAssemblyResolve(RuntimeAssembly? assembly, string assemblyFullName)
{
return InvokeResolveEvent(AssemblyResolve, assembly, assemblyFullName);
}
So its calling the internal AssemblyResolve event, something is setting that.
I found a usage of this in engine code, could it explain the infinite loading requests?
/// <summary>Occurs when the resolution of an assembly fails.</summary>
public event ResolveEventHandler AssemblyResolve;
static void InitAssemblyRedirections()
{
AppDomain.CurrentDomain.AssemblyResolve += (object _, ResolveEventArgs args) =>
{
var sourceAsmName = new AssemblyName(args.Name);
try
{
var loadedAssembly = AppDomain.CurrentDomain.Load(sourceAsmName.Name);
return loadedAssembly;
}
catch
{
// Default if we fail to load for any reason
return null;
}
};
}
Yes, its added to AssemblyLoadContext.AssemblyResolve:
public event ResolveEventHandler? AssemblyResolve
{
add { AssemblyLoadContext.AssemblyResolve += value; }
remove { AssemblyLoadContext.AssemblyResolve -= value; }
}
Kk. Except for ves_icall_System_Reflection_Assembly_InternalLoad
, is there any system icall which can trigger such infinite loading? What can be the best way to bypass such case? Does the workaround make sense?
The c# code needs to make sure it cannot be called recursively.
Description
When targetting WASM without AOT, there is a potential cycle in loading assemblies. Please check the following stacktrace
I changed MONO_LOG_LEVEL to debug and found that it infinitely tried to load a non-existing Module
DOTween.Module
Digging into the code, I found that in https://github.com/dotnet/runtime/blob/4e86b1c63d9c41c6bfb6f42710be907199ce2671/src/mono/mono/metadata/appdomain.c#L806
mono_assembly_request_byname
will recursively try to load moduleDOTween.Modules
until Maximum call stack size exceededReproduction Steps
This is part of a Unity project, and the dll currently loading is
DOTween.dll
. I deassembled it and found the problematic code isExpected behavior
Report error msg but continue execution
Actual behavior
RangeError: Maximum call stack size exceeded and terminate
Regression?
No
Known Workarounds
In single thread situation, a requesting assembly table like
static char s_assemblies_requesting[MAX_ASSEMBLY_LOAD_DEPTH][MAX_ASSEMBLY_NAME_LENGTH]
can be set to check if there is a circular request. And goto fail block when detected or reaching MAX_ASSEMBLY_LOAD_DEPTH.Configuration
.NET8 and .NET9 alpha .\build.cmd -os browser -subset mono+libs It should be browser agnostic.
Other information
DOTween is a Unity plugin and in one of the version it may generate
DOTween.Modules.dll
and in other versions there is no such module generated.