I have two programs, X is the normal program with which the user interacts, and program Y which cleans up the resources acquired by program Y. There can be multiple instances of X but only one of Y (I already solved that part with named mutexes). Now, since Y is a cleanup program, it should be blocked until the last instance of X disappear.
I tried using a semaphore but I couldn’t figure it out. Can somebody help me?
A semaphore is one valid way of doing this, but not necessarily the best. Whenever program X starts, call
ReleaseSemaphore. Whenever a process terminates, callWaitForSingleObjectwith a timeout of zero on the semaphore handle (be sure to also include this in the exception handler, in case the program crashes).Process Y can regularly poll
WaitForSingleObjectwith a zero (or a few milliseconds) timeout then. If the return value isWAIT_OBJECT_0, it must release the semaphore again immediately (otherwise it will block the last X process trying to exit!). If the return value isWAIT_TIMEOUT, there are not X processes any more.The best solution would of course be to launch all X processes from Y. In that case, Y could just
WaitForMultipleObjectson the process handles that it gets fromCreateProcesswith no extra “ifs and whens”. This will “just work”, always. It is more efficient, too.Which leads to the second best solution… getting handles to the running processes with
OpenProcessandWaitForMultipleObjectson those. The problem is where to get the process IDs from. A shared memory area might do, a pipe might do, orCreateToolhelp32Snapshotmight give you that info.Another way would be to use a named mutex object. All processes X call
CreateMutex. If the mutex already exists, no harm is done (GetLastError will returnERROR_ALREADY_EXISTS, but so what). If the process terminates or crashes, all open handles are closed, and thus the mutex reference count is decremented.The Y process calls
OpenMutex. This either succeeds or fails. If it succeeds, it closes the handle again, sleeps, and tries again. If it fails, no single X process is running.Yet another way (though it might possibly have race issues) would be creating a named shared memory segment and calling
InterlockedIncrementandInterlockedDecrementat process X start and exit. Process Y knows that no X processes are running if either the shared memory object cannot be opened or the counter is zero.