Is using a Mutex to prevent multiple instances of the same program from running safe?

Solution 1:

It is more usual and convenient to use Windows events for this purpose. E.g.

static EventWaitHandle s_event ;

bool created ;
s_event = new EventWaitHandle (false, 
    EventResetMode.ManualReset, "my program#startup", out created) ;
if (created) Launch () ;
else         Exit   () ;

When your process exits or terminates, Windows will close the event for you, and destroy it if no open handles remain.

Added: to manage sessions, use Local\ and Global\ prefixes for the event (or mutex) name. If your application is per-user, just append a suitably mangled logged-on user's name to the event name.

Solution 2:

In general yes this will work. However the devil is in the details.

Firstly you want to close the mutex in a finally block. Otherwise your process could abruptly terminate and leave it in a signaled state, like an exception. That would make it so that future process instances would not be able to start up.

Unfortunately though, even with a finally block you must deal with the potential that a process will be terminated without freeing up the mutex. This can happen for instance if a user kills the process through TaskManager. There is a race condition in your code that would allow for a second process to get an AbandonedMutexException in the WaitOne call. You'll need a recovery strategy for this.

I encourage you to read up on the details of the Mutex class. Using it is not always simple.


Expanding upon the race condition possibility:

The following sequence of events can occur which would cause a second instance of the application to throw:

  1. Normal process startup.
  2. Second process starts up and aquires a handle to the mutex but is switched out before the WaitOne call.
  3. Process #1 is abruptly terminated. The mutex is not destroyed because process #2 has a handle. It is instead set to an abandoned state.
  4. The second process starts running again and gets an AbanonedMutexException.

Solution 3:

You can use a mutex, but first make sure that this is really what you want.

Because "avoiding multiple instances" is not clearly defined. It can mean

  1. Avoiding multiple instances started in the same user session, no matter how many desktops that user session has, but allowing multiple instances to run concurrently for different user sessions.
  2. Avoiding multiple instances started in the same desktop, but allowing multiple instances to run as long as each one is in a separate desktop.
  3. Avoiding multiple instances started for the same user account, no matter how many desktops or sessions running under this account exist, but allowing multiple instances to run concurrently for sessions running under a different user account.
  4. Avoiding multiple instances started on the same machine. This means that no matter how many desktops are used by an arbitrary number of users, there can be at most one instance of the program running.

By using a mutex, you're basically using the define number 4.