How to block running two instances of the same program?
There are several methods you can use to accomplish only allowing one instance of your application:
Method 1: Global synchronization object or memory
It's usually done by creating a named global mutex or event. If it is already created, then you know the program is already running.
For example in windows you could do:
#define APPLICATION_INSTANCE_MUTEX_NAME "{BA49C45E-B29A-4359-A07C-51B65B5571AD}"
//Make sure at most one instance of the tool is running
HANDLE hMutexOneInstance(::CreateMutex( NULL, TRUE, APPLICATION_INSTANCE_MUTEX_NAME));
bool bAlreadyRunning((::GetLastError() == ERROR_ALREADY_EXISTS));
if (hMutexOneInstance == NULL || bAlreadyRunning)
{
if(hMutexOneInstance)
{
::ReleaseMutex(hMutexOneInstance);
::CloseHandle(hMutexOneInstance);
}
throw std::exception("The application is already running");
}
Method 2: Locking a file, second program can't open the file, so it's open
You could also exclusively open a file by locking it on application open. If the file is already exclusively opened, and your application cannot receive a file handle, then that means the program is already running. On windows you'd simply not specify sharing flags FILE_SHARE_WRITE
on the file you're opening with CreateFile
API. On linux you'd use flock
.
Method 3: Search for process name:
You could enumerate the active processes and search for one with your process name.
Your method of writing the process pid to a file is a common one that is used in many different established applications. In fact, if you look in your /var/run
directory right now I bet you'll find several *.pid
files already.
As you say, it's not 100% robust because there is chance of the pids getting confused. I have heard of programs using flock()
to lock an application-specific file that will automatically be unlocked by the OS when the process exits, but this method is more platform-specific and less transparent.
I actually use exactly the process you describe, and it works fine except for the edge case that happens when you suddenly run out of disk space and can no longer create files.
The "correct" way to do this is probably to use shared memory: http://www.cs.cf.ac.uk/Dave/C/node27.html
It is very un-unix to prohibit multiple instances of a program to run.
If the program is, say, a network daemon, it doesn't need to actively prohibit multiple instances--only the first instance gets to listen to the socket, so subsequent instances bomb out automatically. If it is, say, an RDBMS, it doesn't need to actively prohibit multiple instances--only the first instance gets to open and lock the files. etc.