Hold singleton mutex open if owned

Still not perfect, thanks to C#'s async threading weirdness it's possible for ownership of the mutex to still be lost - no idea how, but it should mostly work fine.
This commit is contained in:
pizzaboxer 2023-02-19 17:38:02 +00:00
parent 1e46aaa929
commit 222006fa6a
2 changed files with 31 additions and 8 deletions

View File

@ -20,7 +20,7 @@ using Bloxstrap.Models;
namespace Bloxstrap namespace Bloxstrap
{ {
public partial class Bootstrapper public class Bootstrapper
{ {
#region Properties #region Properties
@ -349,7 +349,7 @@ namespace Bloxstrap
// whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes
bool shouldWait = false; bool shouldWait = false;
Mutex singletonMutex; Mutex? singletonMutex = null;
if (App.Settings.Prop.MultiInstanceLaunching) if (App.Settings.Prop.MultiInstanceLaunching)
{ {
@ -357,15 +357,15 @@ namespace Bloxstrap
// this might be a bit problematic since this mutex will be released when the first launched instance is closed... // this might be a bit problematic since this mutex will be released when the first launched instance is closed...
try try
{ {
singletonMutex = Mutex.OpenExisting("ROBLOX_singletonMutex"); Mutex.OpenExisting("ROBLOX_singletonMutex");
App.Logger.WriteLine("[Bootstrapper::StartRoblox] Warning - singleton mutex already exists"); App.Logger.WriteLine("[Bootstrapper::StartRoblox] Warning - singleton mutex already exists!");
} }
catch catch
{ {
singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); singletonMutex = new Mutex(true, "ROBLOX_singletonMutex");
}
shouldWait = true; shouldWait = true;
} }
}
Process gameClient = Process.Start(Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"), _launchCommandLine); Process gameClient = Process.Start(Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"), _launchCommandLine);
List<Process> autocloseProcesses = new(); List<Process> autocloseProcesses = new();
@ -454,6 +454,27 @@ namespace Bloxstrap
App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})");
process.Kill(); 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() public void CancelInstall()

View File

@ -26,12 +26,14 @@ namespace Bloxstrap.Helpers
return -1; return -1;
} }
public static int GetProcessCount(string processName) public static int GetProcessCount(string processName, bool log = true)
{ {
if (log)
App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Checking if '{processName}' is running..."); App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Checking if '{processName}' is running...");
Process[] processes = Process.GetProcessesByName("RobloxPlayerBeta"); Process[] processes = Process.GetProcessesByName("RobloxPlayerBeta");
if (log)
App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Found {processes.Length} process(es) running for '{processName}'"); App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Found {processes.Length} process(es) running for '{processName}'");
return processes.Length; return processes.Length;