Disable assembly load context on content-start client.

This commit is contained in:
Pieter-Jan Briers
2020-03-25 02:13:23 +01:00
parent ff1bfde979
commit d057fdf74f
6 changed files with 70 additions and 6 deletions

View File

@@ -0,0 +1,32 @@
using System.Linq;
using System.Runtime.Loader;
using System.Text;
using JetBrains.Annotations;
using Robust.Client.Interfaces.Console;
namespace Robust.Client.Console.Commands
{
[UsedImplicitly]
internal sealed class ListAssembliesCommand : IConsoleCommand
{
public string Command => "lsasm";
public string Description => "Lists loaded assemblies by load context.";
public string Help => Command;
public bool Execute(IDebugConsole console, string[] args)
{
var sb = new StringBuilder();
foreach (var context in AssemblyLoadContext.All)
{
sb.AppendFormat("{0}:\n", context.Name);
foreach (var assembly in context.Assemblies.OrderBy(a => a.FullName))
{
sb.AppendFormat(" {0}\n", assembly.FullName);
}
}
console.AddLine(sb.ToString());
return false;
}
}
}

View File

@@ -7,7 +7,7 @@ namespace Robust.Client
#if FULL_RELEASE
throw new System.InvalidOperationException("ContentStart is not available on a full release.");
#else
GameController.Start(args);
GameController.Start(args, true);
#endif
}
}

View File

@@ -71,6 +71,7 @@ namespace Robust.Client
#pragma warning restore 649
private CommandLineArgs _commandLineArgs;
private bool _disableAssemblyLoadContext;
public bool LoadConfigAndUserData { get; set; } = true;
@@ -136,6 +137,10 @@ namespace Robust.Client
_fontManager.Initialize();
// Disable load context usage on content start.
// This prevents Content.Client being loaded twice and things like csi blowing up because of it.
_modLoader.SetUseLoadContext(!_disableAssemblyLoadContext);
//identical code for server in baseserver
if (!_modLoader.TryLoadAssembly<GameShared>(_resourceManager, $"Content.Shared"))
{

View File

@@ -23,7 +23,7 @@ namespace Robust.Client
Start(args);
}
public static void Start(string[] args)
public static void Start(string[] args, bool contentStart = false)
{
if (_hasStarted)
{
@@ -34,11 +34,11 @@ namespace Robust.Client
if (CommandLineArgs.TryParse(args, out var parsed))
{
ParsedMain(parsed);
ParsedMain(parsed, contentStart);
}
}
private static void ParsedMain(CommandLineArgs args)
private static void ParsedMain(CommandLineArgs args, bool contentStart)
{
IoCManager.InitThread();
@@ -48,6 +48,7 @@ namespace Robust.Client
var gc = (GameController) IoCManager.Resolve<IGameController>();
gc.SetCommandLineArgs(args);
gc._disableAssemblyLoadContext = contentStart;
if (!gc.Startup())
{
Logger.Fatal("Failed to start game controller!");

View File

@@ -44,5 +44,7 @@ namespace Robust.Shared.ContentPack
/// Sets the testing callbacks that will be passed to <see cref="GameShared.SetTestingCallbacks"/>.
/// </summary>
void SetModuleBaseCallbacks(ModuleTestingCallbacks testingCallbacks);
void SetUseLoadContext(bool useLoadContext);
}
}

View File

@@ -78,6 +78,8 @@ namespace Robust.Shared.ContentPack
private static int _modLoaderId;
private bool _useLoadContext;
public ModLoader()
{
var id = Interlocked.Increment(ref _modLoaderId);
@@ -88,6 +90,11 @@ namespace Robust.Shared.ContentPack
_loadContext.Resolving += ResolvingAssembly;
}
public void SetUseLoadContext(bool useLoadContext)
{
_useLoadContext = useLoadContext;
}
public virtual void LoadGameAssembly<T>(Stream assembly, Stream symbols = null)
where T : GameShared
{
@@ -101,7 +108,15 @@ namespace Robust.Shared.ContentPack
assembly.Position = 0;
var gameAssembly = _loadContext.LoadFromStream(assembly, symbols);
Assembly gameAssembly;
if (_useLoadContext)
{
gameAssembly = _loadContext.LoadFromStream(assembly, symbols);
}
else
{
gameAssembly = Assembly.Load(assembly.CopyToArray(), symbols.CopyToArray());
}
InitMod<T>(gameAssembly);
}
@@ -118,7 +133,16 @@ namespace Robust.Shared.ContentPack
if (!AssemblyTypeChecker.CheckAssembly(diskPath))
return;
InitMod<T>(_loadContext.LoadFromAssemblyPath(diskPath));
Assembly assembly;
if (_useLoadContext)
{
assembly = _loadContext.LoadFromAssemblyPath(diskPath);
}
else
{
assembly = Assembly.LoadFrom(diskPath);
}
InitMod<T>(assembly);
}
protected void InitMod<T>(Assembly assembly) where T : GameShared