C#, Mono, and System-Wide Mutexes on Linux

Here’s another little “gotcha” from my experimentations in running C# apps cross-platform. The following code implements a system-wide mutex to ensure that only one instance of the program is running at any one time:

public static void Main(string[] args){
	Mutex mutex = null;
	try{
		mutex = Mutex.OpenExisting("test.martyndavis.com");
		// if we *can* open it we're an ADDITIONAL instance
		Console.WriteLine("Application is already running");
		return;
	} catch(WaitHandleCannotBeOpenedException){
		// if we get in here then the mutex doesn't exist,
		// so we are the only instance running on this machine
        mutex = new System.Threading.Mutex(true, "test.martyndavis.com");
	}
	try{
		Console.WriteLine("Doing stuff... press a key");
        Console.Read();
	} finally{
		// Although mutex implements IDisposable, it doesn't
		// call Release Mutex when being Disposed(),
		// hence usage of try/finally instead of 'using'.
		mutex.ReleaseMutex();
	}
}

Running this on Windows it behaves as one would expect. Run one instance you get “Doing stuff… press a key” output, and, if you try to run a second instance in another DOS box you get “Application is already running”.

On Linux though it’s a different story – each instance runs as if it’s the only copy on the machine.

Doing some digging turns up this note in Mono’s release docs – you can see that shared handles are now turned off by default – you can turn them on by setting the environment variable¬†MONO_ENABLE_SHM, but for the application I’m working on I think I’ll simply avoid mutexes and use something else to ensure one instance – a lock file in the application’s data directory will be simple, and work cross-platform.

Leave a Reply

Your email address will not be published. Required fields are marked *