Cross-Platform Mutex Behavior in .NET: Windows vs Linux
The Mutex class in C# enables cross-process synchronization on Windows, making it suitable for singleton instance detection. However, this capability breaks down in Linux environments for both Mono and .NET Core (3.1) runtimes.
Test Implementation
using System;
using System.Threading;
namespace MutexTest
{
class Application
{
static void Main(string[] args)
{
bool isNewInstance;
using var syncLock = new Mutex(true, "Global\\SingletonIdentifier", out isNewInstance);
var timestamp = DateTime.UtcNow.ToString("o");
if (!isNewInstance)
{
Console.WriteLine($"{timestamp} - Another instance detected via mutex.");
}
else
{
Console.WriteLine($"{timestamp} - Initialized mutex: {syncLock.SafeWaitHandle.DangerousGetHandle()}");
}
using var secondLock = new Mutex(true, "Global\\SingletonIdentifier", out isNewInstance);
if (!isNewInstance)
{
Console.WriteLine($"{timestamp} - Second attempt: instance already running.");
}
else
{
Console.WriteLine($"{timestamp} - Second mutex created unexpectedly.");
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey(true);
}
}
}
.NET Coree Runtime Behavior on Ubuntu
Step 1: Execute the compiled application with dotnet run.
Step 2: Inspect the /tmp directory using a file transfer utility. Each process creates its own set of named pipe files that remain isolated from other instances. The dotnet-diagnostic-{pid}-{random-id}-socket file serves as a diagnostic socket endpoint for the .NET runtime.
Step 3: Launch a second instance. Notice that the second processs creates a completely separate set of pipe files with no interference from the first instance.
Finding: .NET Core creates independent named pipe resources per process in /tmp. These pipes do not communicate, meaning the Mutex fails to provide cross-process synchronization on Linux.
Mono Runtime Behavior on Ubuntu
Compilation:
mono-csc Program.cs
Execution:
mono Program.exe
Observations: When running multiple instances simultaneously across separate terminal sessions, each process reports itself as the "initial" instance. The Mutex fails to recognize other processes holding the same name.
This behavior aligns with documented limitasions:
Mono does not implement Windows-native IPC mechanisms. Named Pipes, Event objects, and Mutexes are not available for cross-process synchronization.
Alternative Approaches for Linux
To achieve reliable singleton behavior on Linux platforms, consider:
- File-based locking: Create and lock a file using
FileStreamwith exclusive access - Unix domain sockets: Bind to a specific socket path and catch address-in-use exceptions
- Distributed locks: Use external systems like Redis or ZooKeeper for cluster-wide coordination