From 333419d89c60dbecc9eefae128252ee9ea750320 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2024 17:33:08 +0900 Subject: [PATCH] Fix multiple instances of a game being allowed to start concurrently Regressed with https://github.com/ppy/osu-framework/pull/6442. Was not visible in test coverage because as per the inline comment, this is an exceptional case where two different processes bind. I'm not sure how to add test coverage for this, but I have tested manually on both windows and macOS. --- .../Platform/NamedPipeIpcProvider.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Framework/Platform/NamedPipeIpcProvider.cs b/osu.Framework/Platform/NamedPipeIpcProvider.cs index 32f6daea2fb..1cc39b6bb11 100644 --- a/osu.Framework/Platform/NamedPipeIpcProvider.cs +++ b/osu.Framework/Platform/NamedPipeIpcProvider.cs @@ -34,6 +34,8 @@ public class NamedPipeIpcProvider : IDisposable private NamedPipeServerStream? pipe; + private Mutex? mutex; + /// /// Create a new provider. /// @@ -57,7 +59,17 @@ public bool Bind() try { - pipe = new NamedPipeServerStream($"osu-framework-{pipeName}", PipeDirection.InOut); + string name = $"osu-framework-{pipeName}"; + + // Named pipes from different processes are allowed to coexist, but we don't want this for our purposes. + // Using a system global mutex allows ensuring that only one osu!framework project using the same pipe name + // will be able to bind. + mutex = new Mutex(false, $"Global\\{name}", out bool createdNew); + + if (!createdNew) + return false; + + pipe = new NamedPipeServerStream(name, PipeDirection.InOut, 1); listenTask = listen(pipe); @@ -110,7 +122,8 @@ private async Task listen(NamedPipeServerStream pipe) { try { - pipe.Disconnect(); + if (pipe.IsConnected) + pipe.Disconnect(); } catch { @@ -202,6 +215,8 @@ public void Dispose() cancellationSource.Cancel(); + mutex?.Dispose(); + if (listenTask != null) { try