HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpCritical

What is a good pattern for using a Global Mutex in C#?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
mutexgoodglobalusingforpatternwhat

Problem

The Mutex class is very misunderstood, and Global mutexes even more so.

What is good, safe pattern to use when creating Global mutexes?

One that will work

  • Regardless of the locale my machine is in



  • Is guaranteed to release the mutex properly



  • Optionally does not hang forever if the mutex is not acquired



  • Deals with cases where other processes abandon the mutex

Solution

I want to make sure this is out there, because it's so hard to get right:
using System.Runtime.InteropServices; //GuidAttribute
using System.Reflection; //Assembly
using System.Threading; //Mutex
using System.Security.AccessControl; //MutexAccessRule
using System.Security.Principal; //SecurityIdentifier

static void Main(string[] args)
{
// get application GUID as defined in AssemblyInfo.cs
string appGuid =
((GuidAttribute) Assembly
.GetExecutingAssembly()
.GetCustomAttributes(typeof(GuidAttribute), false)
.GetValue(0)
).Value.ToString();

// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);

// Need a place to store a return value in Mutex() constructor call
bool createdNew;

// edited by Jeremy Wiebe to add example of setting up security for multi-user usage
// edited by 'Marc' to work also on localized systems (don't use just "Everyone")
var allowEveryoneRule =
new MutexAccessRule(
new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.FullControl,
AccessControlType.Allow
);

var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);

// edited by MasonGZhwiti to prevent race condition on security settings via VanNguyen
using (var mutex = new Mutex(false, mutexId, out createdNew, securitySettings))
{
// edited by acidzombie24
var hasHandle = false;
try
{
try
{
// note, you may want to time out here instead of waiting forever
// edited by acidzombie24
// mutex.WaitOne(Timeout.Infinite, false);
hasHandle = mutex.WaitOne(5000, false);
if (hasHandle == false) {
throw new TimeoutException("Timeout waiting for exclusive access");
}
}
catch (AbandonedMutexException)
{
// Log the fact that the mutex was abandoned in another process,
// it will still get acquired
hasHandle = true;
}

// Perform your work here.
}
finally
{
// edited by acidzombie24, added if statement
if(hasHandle) {
mutex.ReleaseMutex();
}
}
}
}

Context

Stack Overflow Q#229565, score: 451

Revisions (0)

No revisions yet.