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.