From d1b75f6874aafb0e28699f7fac15e091749760de Mon Sep 17 00:00:00 2001 From: pizzaboxer <41478239+pizzaboxer@users.noreply.github.com> Date: Wed, 8 Mar 2023 23:34:44 +0000 Subject: [PATCH] Fix singleton mutex handling (for real) (#99) --- Bloxstrap/App.xaml.cs | 44 ++++++++++++++++++++++++++++++++++ Bloxstrap/Bootstrapper.cs | 38 ----------------------------- Bloxstrap/Helpers/Utilities.cs | 4 +++- 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 588b1b5..3f6aa9c 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -230,6 +230,28 @@ namespace Bloxstrap dialog.Bootstrapper = bootstrapper; } + // handle roblox singleton mutex for multi-instance launching + // note we're handling it here in the main thread and NOT in the + // bootstrapper as handling mutexes in async contexts suuuuuucks + + Mutex? singletonMutex = null; + + if (Settings.Prop.MultiInstanceLaunching) + { + Logger.WriteLine("[App::OnStartup] Creating singleton mutex"); + + try + { + Mutex.OpenExisting("ROBLOX_singletonMutex"); + Logger.WriteLine("[App::OnStartup] Warning - singleton mutex already exists!"); + } + catch + { + // this might be a bit problematic since this mutex will be released when the first launched instance is closed... + singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); + } + } + Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t => { Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished"); @@ -250,6 +272,28 @@ namespace Bloxstrap dialog?.ShowBootstrapper(); bootstrapperTask.Wait(); + + if (singletonMutex is not null) + { + // we've got ownership of the roblox singleton mutex! + // if we stop running, everything will screw up once any more roblox instances launched + // also this code is blehhhh im sure theres a better way of checking if the process count changed like this + + int runningProcesses = -1; + while (runningProcesses != 0) + { + int runningProcessesNow = Utilities.GetProcessCount("RobloxPlayerBeta", false); + + if (runningProcessesNow != runningProcesses) + { + Logger.WriteLine($"[App::OnStartup] We have singleton mutex ownership! Running in background until all Roblox processes are closed ({runningProcessesNow} remaining)..."); + runningProcesses = runningProcessesNow; + } + + // hmm... good idea to do this on main thread? + Task.Delay(5000); + } + } } Terminate(); diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 8efda9d..3324ec5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -322,23 +322,6 @@ namespace Bloxstrap // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes bool shouldWait = false; - Mutex? singletonMutex = null; - - if (App.Settings.Prop.MultiInstanceLaunching) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Creating singleton mutex"); - // this might be a bit problematic since this mutex will be released when the first launched instance is closed... - try - { - Mutex.OpenExisting("ROBLOX_singletonMutex"); - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Warning - singleton mutex already exists!"); - } - catch - { - singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); - shouldWait = true; - } - } Process gameClient = Process.Start(Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"), _launchCommandLine); List autocloseProcesses = new(); @@ -427,27 +410,6 @@ namespace Bloxstrap App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); process.Kill(); } - - if (singletonMutex is not null) - { - // we've got ownership of the roblox singleton mutex! - // if we stop running, everything will screw up once any more instances launched - // also this code is blehhhh im sure theres a better way of checking if the process count changed like this - - int runningProcesses = -1; - while (runningProcesses != 0) - { - int runningProcessesNow = Utilities.GetProcessCount("RobloxPlayerBeta", false); - - if (runningProcessesNow != runningProcesses) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] We have singleton mutex ownership! Running in background until all Roblox processes are closed ({runningProcessesNow} remaining)..."); - runningProcesses = runningProcessesNow; - } - - await Task.Delay(5000); - } - } } public void CancelInstall() diff --git a/Bloxstrap/Helpers/Utilities.cs b/Bloxstrap/Helpers/Utilities.cs index 928e928..7627449 100644 --- a/Bloxstrap/Helpers/Utilities.cs +++ b/Bloxstrap/Helpers/Utilities.cs @@ -52,8 +52,10 @@ namespace Bloxstrap.Helpers string json = await App.HttpClient.GetStringAsync(url); return JsonSerializer.Deserialize(json); } - catch (Exception) + catch (Exception ex) { + App.Logger.WriteLine($"[Utilities::GetJson<{typeof(T).Name}>] Failed to deserialize JSON!"); + App.Logger.WriteLine($"[Utilities::GetJson<{typeof(T).Name}>] {ex}"); return default; } }