I have two instances running of same Windows Service. They check the health of each other and report if any issue is found. I have a critical job that needs to be performed so I am running it with a fail-over approach, it runs in Master, and if Master is not responding it runs in slave. This job needs to communicate over a specific serial port, I am trying to use Mutex to check for race condition. I dont have access to production, so before deploying I want to make sure my approach is fine. So please suggest if my use of Mutex is fine for the given case.
if (iAmRunningInSlave)
{
HealthClient hc = new HealthClient();
if (!hc.CheckHealthOfMaster())
return this.runJobWrapper(withMutex, iAmRunningInSlave);
else
return true; //master is ok, we dont need to run the job in slave
}
return this.runJobWrapper(withMutex, iAmRunningInSlave);
And then in runJobWrapper
bool runJobWrapper(bool withMutex, bool iAmRunningInSlave)
{
if (!withMutex)
return this.runJob(iAmRunningInSlave); //the job might be interested to know
Mutex mutex = null;
string mutexName = this.jobCategory + "-" + this.jobTitle; //this will be unique for given job
try
{
mutex = Mutex.OpenExisting(mutexName);
return false; //mutex is with peer, return false which will re-trigger slave
}
catch
{
try
{ //mean time mutex might have created, so wrapping in try/catch
mutex = new Mutex(true /*initiallyOwned*/, mutexName);
return this.runJob(iAmRunningInSlave); //the job might be interested to know where I am running
}
finally
{
if (null!=mutex) mutex.ReleaseMutex();
}
return false;
}
}
I had a similar issue recently.
The design of the
Mutex
class is a bit weird/different from the normal classes in .NET.Using
OpenMutex
to check for an existingMutex
is not really nice as you have to catch an exception.A better approach is to use the
constructor, and check the value returned by
createdNew
.You don't look to check the return value from
runJobWrapper
anywhere - is this intentional? It is not obvious what the return value actually means anyway. Also you really shouldn't catch each any every exception thatOpenExisiting
could possibly throw - Out of memory? Stack overflow? etc. etc. Just catch the one you mean to handle correctly.Also your code looks to be somewhat fragile - I wouldn't be surprised if you have race conditions.
I noticed that mutex.ReleaseMutex() was not releasing the mutex immediately..I had to call GC.Collect()