Skip to content

Commit 381dbf6

Browse files
committed
Fix restarting process won't actually restarting
1 parent 15671a7 commit 381dbf6

1 file changed

Lines changed: 67 additions & 46 deletions

File tree

CollapseLauncher/Program.cs

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using CollapseLauncher.Helper.Database;
44
using CollapseLauncher.Helper.Update;
55
using Hi3Helper;
6+
using Hi3Helper.Data;
67
using Hi3Helper.EncTool;
78
using Hi3Helper.EncTool.Hashes;
89
using Hi3Helper.Http.Legacy;
@@ -19,6 +20,7 @@
1920
using PhotoSauce.NativeCodecs.Libjxl;
2021
using PhotoSauce.NativeCodecs.Libwebp;
2122
using System;
23+
using System.Buffers;
2224
using System.Diagnostics;
2325
using System.Globalization;
2426
using System.IO;
@@ -58,7 +60,8 @@ public static void Main(params string[] args)
5860
{
5961
try
6062
{
61-
AppCurrentArgument = args.ToList();
63+
args = KillParentPidIfRestartRequested(args);
64+
AppCurrentArgument = [.. args];
6265
#if PREVIEW
6366
IsPreview = true;
6467
#endif
@@ -116,7 +119,6 @@ public static void Main(params string[] args)
116119
// Reason: These are methods that either has its own error handling and/or not that important,
117120
// so the execution could continue without anything to worry about **technically**
118121
CheckRuntimeFeatures();
119-
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
120122

121123
Console.WriteLine(Directory.GetCurrentDirectory());
122124
Application.Start(_ =>
@@ -419,22 +421,7 @@ public static void SpawnFatalErrorConsole(Exception ex)
419421

420422
if (ConsoleKey.R == Console.ReadKey().Key)
421423
{
422-
ProcessStartInfo startInfo = new()
423-
{
424-
FileName = AppExecutablePath,
425-
UseShellExecute = false
426-
};
427-
428-
foreach (string arg in AppCurrentArgument)
429-
{
430-
startInfo.ArgumentList.Add(arg);
431-
}
432-
433-
Process process = new()
434-
{
435-
StartInfo = startInfo
436-
};
437-
process.Start();
424+
ForceRestart();
438425
}
439426

440427
tokenSource.Cancel();
@@ -603,14 +590,6 @@ private static void HttpClientLogWatcher(object sender, DownloadLogEvent e)
603590
LogWriteLine(e.Message, severity, true);
604591
}
605592

606-
private static void OnProcessExit(object? sender, EventArgs e)
607-
{
608-
// TODO: #671 This App.IsAppKilled will be replaced with cancellable-awaitable event
609-
// to ensure no hot-exit being called before all background tasks
610-
// hasn't being cancelled.
611-
// App.IsAppKilled = true;
612-
}
613-
614593
private static void CheckRuntimeFeatures()
615594
{
616595
try
@@ -664,19 +643,15 @@ private static void InitLocale()
664643

665644
private static void RunElevateUpdate()
666645
{
667-
Process elevatedProc = new Process
646+
Process? elevatedProc = Process.Start(new ProcessStartInfo
668647
{
669-
StartInfo = new ProcessStartInfo
670-
{
671-
FileName = UpdaterWindow.SourcePath,
672-
WorkingDirectory = UpdaterWindow.WorkingDir,
673-
Arguments =
674-
$"update --input \"{m_arguments.Updater.AppPath}\" --channel {m_arguments.Updater.UpdateChannel}",
675-
UseShellExecute = true,
676-
Verb = "runas"
677-
}
678-
};
679-
elevatedProc.Start();
648+
FileName = UpdaterWindow.SourcePath,
649+
WorkingDirectory = UpdaterWindow.WorkingDir,
650+
Arguments = $"update --input \"{m_arguments.Updater.AppPath}\" --channel {m_arguments.Updater.UpdateChannel}",
651+
UseShellExecute = true,
652+
Verb = "runas"
653+
});
654+
elevatedProc?.Start();
680655
}
681656

682657
public static string GetVersionString()
@@ -693,24 +668,70 @@ public static string MD5Hash(string path)
693668
return "";
694669
}
695670

696-
FileStream stream = File.OpenRead(path);
697-
byte[] hash = CryptoHashUtility<MD5>.Shared.GetHashFromStream(stream);
698-
stream.Close();
671+
using FileStream stream = File.OpenRead(path);
672+
byte[] hash = CryptoHashUtility<MD5>.Shared.GetHashFromStream(stream);
699673
return Convert.ToHexStringLower(hash);
700674
}
701675

676+
private static string restartedFromPidArgKey = "restartedFromPid";
677+
702678
public static void ForceRestart()
703679
{
704680
// Workaround to artificially start new process and wait for the current one to be killed.
705-
var cmdProc = Process.Start(new ProcessStartInfo
681+
using Process? cmdProc = Process.Start(new ProcessStartInfo
706682
{
707-
FileName = "cmd.exe",
708-
Arguments = $"/c timeout /T 1 && start \"\" \"{AppExecutablePath}\"",
709-
UseShellExecute = true,
683+
FileName = AppExecutablePath,
684+
WorkingDirectory = Environment.CurrentDirectory,
685+
Arguments = $"{restartedFromPidArgKey}:{Environment.ProcessId} {string.Join(' ', AppCurrentArgument)}",
686+
UseShellExecute = true
710687
});
711688

712-
cmdProc?.WaitForExit();
713689
Application.Current.Exit();
714690
}
691+
692+
private static string[] KillParentPidIfRestartRequested(params string[] args)
693+
{
694+
if (args.Length == 0)
695+
{
696+
return args;
697+
}
698+
699+
int indexOfArg = -1;
700+
string[] restArgs = args.Length == 1 ? [] : new string[args.Length - 1];
701+
702+
// Copy other args and find restart arg
703+
for (int i = 0; i < args.Length; i++)
704+
{
705+
string currentArg = args[i];
706+
if (currentArg.StartsWith(restartedFromPidArgKey, StringComparison.OrdinalIgnoreCase))
707+
{
708+
indexOfArg = i;
709+
continue;
710+
}
711+
restArgs[i < indexOfArg ? i : i - 1] = currentArg;
712+
}
713+
714+
if (indexOfArg < 0)
715+
{
716+
return args;
717+
}
718+
719+
ReadOnlySpan<char> restartParentPidArg = args[indexOfArg];
720+
ReadOnlySpan<char> restartParentPid = ConverterTool.GetSplit(restartParentPidArg, 1, ":,#$;");
721+
722+
// Check for PID. If exist, then kill.
723+
if (!int.TryParse(restartParentPid, out int parentPid) ||
724+
!ProcessChecker.IsProcessExist(parentPid))
725+
{
726+
return restArgs;
727+
}
728+
729+
Console.WriteLine($"Waiting to kill parent process: {parentPid}");
730+
using Process parentProcess = Process.GetProcessById(parentPid);
731+
parentProcess.Kill();
732+
parentProcess.WaitForExit();
733+
734+
return restArgs;
735+
}
715736
}
716737
}

0 commit comments

Comments
 (0)