I am using Semaphore to limit the number of concurrent instances my application can run.
There are many ways a process can terminate. Can the Semaphore
The appropriate answer is to implement a 'Critical Finalizer' around your semaphore to ensure proper clean-up in all cases. ProcessExit is not guaranteed to execute in a failure scenario, such as a forced appdomain unload due to non-trappable exceptions (StackOverflowException and InvalidProgramException being two good examples.)
More info @ http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.criticalfinalizerobject.aspx, to quote: "the common language runtime (CLR) guarantees that all critical finalization code will be given the opportunity to execute, provided the finalizer follows the rules for a CER, even in situations where the CLR forcibly unloads an application domain or aborts a thread."