I am not sure to have well understood how to handle mutex. I need that a process run only once, but if for any reason it crash or close unexpectedly, i also need to reset the abandoned mutex.
For that reason i made an helper calls that try to acquire a mutex (identified by name) with a timeout. If it fail to acquire the mutex then return NULL otherwise it return the mutex that will be handled by the method caller. If the mutex is abandoned i will reset it and consider the request as failed (is not an issue that code is inteded to be used in periodic procedure, if a lock sometimes fail then the procedure will resume into the next run).
What i am asking for is if there is some situation i have not considered that may cause me problem
Here the code :
public class MutexManager
{
/// <summary>
/// Try to acquire a global mutex
/// </summary>
/// <param name="mutexName">Mutex unique name</param>
/// <param name="timeout_ms">Timeout in milliseconds (Optional : default = 5000, if <= 0 no timeout is applied, infinite wait and possibile daeadlock) </param>
/// <returns>The acquired Mutex or null if Mutex can not be acquired</returns>
public static Mutex TryRegister(string mutexName, int timeout_ms = 5000)
{
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", mutexName);
bool createdNew;
var allowEveryoneRule =new MutexAccessRule( new SecurityIdentifier(WellKnownSidType.WorldSid
, null)
, MutexRights.FullControl
, AccessControlType.Allow
);
Mutex mutex = null;
{
mutex = new Mutex(false, mutexId, out createdNew);
var hasHandle = false;
try
{
hasHandle = mutex.WaitOne(timeout_ms, false);
if (hasHandle == false)
return null;
else
return mutex;
}
catch (AbandonedMutexException)
{
mutex.ReleaseMutex();
mutex.Close();
mutex.Dispose();
return null;
}
catch (Exception err)
{
return null;
}
}
}
}
Here how i will use the class above. The code below is used in periodic procedure (scheduled throght windows scheduler) so if sometimes thing gone wrong is not an issue (next run will do the work) the important think is that there are no race-condition or deead-lock
using ( var mutex = MutexManager.TryRegister("procedureName") )
{
...DO WORK
}