From 958c6bb70436b73b363b298e0efe5e1e5839cfd2 Mon Sep 17 00:00:00 2001 From: Archi Date: Mon, 22 Nov 2021 22:36:38 +0100 Subject: [PATCH] Fix for OS-specific builds not being able to restart after update --- ArchiSteamFarm/Core/ASF.cs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index c739f7fb4..8b91eb0e6 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -77,6 +77,7 @@ public static class ASF { internal static ICrossProcessSemaphore? RateLimitingSemaphore { get; private set; } internal static ImmutableDictionary? WebLimitingSemaphores { get; private set; } + private static readonly ImmutableHashSet AssembliesNeededBeforeUpdate = ImmutableHashSet.Create("System.IO.Pipes"); private static readonly SemaphoreSlim UpdateSemaphore = new(1, 1); private static Timer? AutoUpdatesTimer; @@ -419,17 +420,31 @@ public static class ASF { }.ToImmutableDictionary(); } + private static void LoadAssembliesNeededBeforeUpdate() { + HashSet loadedAssembliesNames = new(); + + foreach (Assembly assembly in AssembliesNeededBeforeUpdate.Select(Assembly.Load)) { + LoadAssembliesRecursively(assembly, loadedAssembliesNames); + } + } + [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "We don't care about trimmed assemblies, as we need it to work only with the known (used) ones")] private static void LoadAssembliesRecursively(Assembly assembly, HashSet? loadedAssembliesNames = null) { if (assembly == null) { throw new ArgumentNullException(nameof(assembly)); } - if (loadedAssembliesNames == null) { + if ((loadedAssembliesNames == null) || (loadedAssembliesNames.Count == 0)) { Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); // ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework - loadedAssembliesNames = loadedAssemblies.Select(static loadedAssembly => loadedAssembly.FullName).Where(static name => !string.IsNullOrEmpty(name)).ToHashSet()!; + IEnumerable loadedAssembliesEnumerable = loadedAssemblies.Select(static loadedAssembly => loadedAssembly.FullName).Where(static name => !string.IsNullOrEmpty(name))!; + + if (loadedAssembliesNames == null) { + loadedAssembliesNames = loadedAssembliesEnumerable.ToHashSet(); + } else { + loadedAssembliesNames.UnionWith(loadedAssembliesEnumerable); + } } foreach (AssemblyName assemblyName in assembly.GetReferencedAssemblies().Where(assemblyName => !loadedAssembliesNames.Contains(assemblyName.FullName))) { @@ -924,6 +939,11 @@ public static class ASF { LoadAssembliesRecursively(Assembly.GetExecutingAssembly()); } + // This is a tricky one, for some reason we might need to preload some selected assemblies even in OS-specific builds that normally should be self-contained... + // It's as if the executable file was directly mapped to memory and moving it out of the original path caused the whole thing to crash + // TODO: This is a total hack, I wish we could get to the bottom of this hole and find out what is really going on there in regards to the above + LoadAssembliesNeededBeforeUpdate(); + // Firstly we'll move all our existing files to a backup directory string backupDirectory = Path.Combine(targetDirectory, SharedInfo.UpdateDirectory);