- Fixed ACL name not being shown in warnings.

- Fixed thread lock recursion causing fileloadexceptions.
This commit is contained in:
MapleWheels
2023-10-26 16:25:01 -04:00
parent 2a931142a0
commit e2695db011
3 changed files with 42 additions and 15 deletions
@@ -352,13 +352,25 @@ public class AssemblyManager
{ {
OpsLockLoaded.ExitReadLock(); OpsLockLoaded.ExitReadLock();
} }
} }
#endregion #endregion
#region InternalAPI #region InternalAPI
/// <summary>
/// [Unsafe] Warning: only for use in nested threading functions. Requires care to manage access.
/// Does not make any guarantees about the state of the ACL after the list has been returned.
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.Synchronized | MethodImplOptions.NoInlining)]
internal ImmutableList<LoadedACL> UnsafeGetAllLoadedACLs()
{
if (LoadedACLs.IsEmpty)
return ImmutableList<LoadedACL>.Empty;
return LoadedACLs.Select(kvp => kvp.Value).ToImmutableList();
}
/// <summary> /// <summary>
/// Used by content package and plugin management to stop unloading of a given ACL until all plugins have gracefully closed. /// Used by content package and plugin management to stop unloading of a given ACL until all plugins have gracefully closed.
/// </summary> /// </summary>
@@ -295,15 +295,16 @@ public sealed class CsPackageManager : IDisposable
_assemblyManager.OnAssemblyUnloading += AssemblyManagerOnAssemblyUnloading; _assemblyManager.OnAssemblyUnloading += AssemblyManagerOnAssemblyUnloading;
// log error if some ACLs are still unloading (some assembly is still in use) // log error if some ACLs are still unloading (some assembly is still in use)
_assemblyManager.FinalizeDispose(); //Update lists
if (_assemblyManager.IsCurrentlyUnloading) if (_assemblyManager.IsCurrentlyUnloading)
{ {
ModUtils.Logging.PrintWarning($"WARNING: Some mods from a previous session (lobby) are still loaded! This may result in undefined behaviour!\nIf you notice any odd behaviour that only occurs after multiple lobbies, please restart your game."); ModUtils.Logging.PrintWarning($"WARNING: Some mods from a previous session (lobby) are still loaded! This may result in undefined behaviour!\nIf you notice any odd behaviour that only occurs after multiple lobbies, please restart your game.");
ModUtils.Logging.PrintWarning($"The below ACLs are still unloading:");
foreach (var wkref in _assemblyManager.StillUnloadingACLs) foreach (var wkref in _assemblyManager.StillUnloadingACLs)
{ {
ModUtils.Logging.PrintWarning($"The below ACL is still unloading:");
if (wkref.TryGetTarget(out var tgt)) if (wkref.TryGetTarget(out var tgt))
{ {
ModUtils.Logging.PrintWarning($"ACL Name: {tgt.Name}"); ModUtils.Logging.PrintWarning($"ACL Name: {tgt.FriendlyName}");
foreach (Assembly assembly in tgt.Assemblies) foreach (Assembly assembly in tgt.Assemblies)
{ {
ModUtils.Logging.PrintWarning($"-- Assembly: {assembly.GetName()}"); ModUtils.Logging.PrintWarning($"-- Assembly: {assembly.GetName()}");
@@ -280,20 +280,33 @@ public class MemoryFileAssemblyContextLoader : AssemblyLoadContext
} }
//try resolve against other loaded alcs //try resolve against other loaded alcs
foreach (var loadedAcL in _assemblyManager.GetAllLoadedACLs()) ImmutableList<AssemblyManager.LoadedACL> list;
try
{ {
if (loadedAcL.Acl is null || loadedAcL.Acl.IsTemplateMode || loadedAcL.Acl.IsDisposed) list = _assemblyManager.UnsafeGetAllLoadedACLs();
continue; }
catch
{
list = ImmutableList<AssemblyManager.LoadedACL>.Empty;
}
try if (!list.IsEmpty)
{
foreach (var loadedAcL in list)
{ {
ass = loadedAcL.Acl.LoadFromAssemblyName(assemblyName); if (loadedAcL.Acl is null || loadedAcL.Acl.IsTemplateMode || loadedAcL.Acl.IsDisposed)
if (ass is not null) continue;
return ass;
} try
catch {
{ ass = loadedAcL.Acl.LoadFromAssemblyName(assemblyName);
// LoadFromAssemblyName throws, no need to propagate if (ass is not null)
return ass;
}
catch
{
// LoadFromAssemblyName throws, no need to propagate
}
} }
} }
@@ -315,6 +328,7 @@ public class MemoryFileAssemblyContextLoader : AssemblyLoadContext
CompiledAssembly = null; CompiledAssembly = null;
CompiledAssemblyImage = null; CompiledAssemblyImage = null;
_dependencyResolvers.Clear(); _dependencyResolvers.Clear();
_assemblyManager = null;
base.Unloading -= OnUnload; base.Unloading -= OnUnload;
this.IsDisposed = true; this.IsDisposed = true;
} }