[ACCEPTED]-How to block running two instances of the same program?-c++
There are several methods you can use to 15 accomplish only allowing one instance of 14 your application:
Method 1: Global synchronization object or memory
It's usually done by creating 13 a named global mutex or event. If it is 12 already created, then you know the program 11 is already running.
For example in windows 10 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 9 open a file by locking it on application 8 open. If the file is already exclusively 7 opened, and your application cannot receive 6 a file handle, then that means the program 5 is already running. On windows you'd simply 4 not specify sharing flags FILE_SHARE_WRITE
on the file you're 3 opening with CreateFile
API. On linux you'd use flock
.
Method 3: Search for process name:
You 2 could enumerate the active processes and 1 search for one with your process name.
Your method of writing the process pid to 11 a file is a common one that is used in many 10 different established applications. In fact, if 9 you look in your /var/run
directory right now I 8 bet you'll find several *.pid
files already.
As 7 you say, it's not 100% robust because there 6 is chance of the pids getting confused. I 5 have heard of programs using flock()
to lock an 4 application-specific file that will automatically 3 be unlocked by the OS when the process exits, but 2 this method is more platform-specific and 1 less transparent.
I actually use exactly the process you describe, and 5 it works fine except for the edge case that 4 happens when you suddenly run out of disk 3 space and can no longer create files.
The 2 "correct" way to do this is probably 1 to use shared memory: http://www.cs.cf.ac.uk/Dave/C/node27.html
It is very un-unix to prohibit multiple 9 instances of a program to run.
If the program 8 is, say, a network daemon, it doesn't need 7 to actively prohibit multiple instances--only 6 the first instance gets to listen to the 5 socket, so subsequent instances bomb out 4 automatically. If it is, say, an RDBMS, it 3 doesn't need to actively prohibit multiple 2 instances--only the first instance gets 1 to open and lock the files. etc.
If you want something that's bog standard, then 13 using a file as a 'lock' is pretty much 12 the way to go. It does have the drawback 11 that you mentioned (if your app doesn't 10 clean up, restarting can be an issue).
This 9 method is used by quite a few applications, but 8 the only one I can recall off the top of 7 my head is VMware. And yes, there are times 6 when you have to go in and delete the '*.lck' when 5 things get wedged.
Using a global mutex or 4 other system object as mentioned by Brian Bondy is 3 a better way to go, but these are platform 2 specific, (unless you use some other library 1 to abstract the platform specifics away).
I don't have a good solution, but two thoughts:
You 7 could add a ping capability to query the 6 other process and make sure it's not an 5 unrelated process. Firefox does something 4 similar on Linux and doesn't start a new 3 instance when one is already running.
If 2 you use a signal handler, you can ensure 1 the pid file is deleted on all but a
kill -9
I scan the process list looking for the 10 name of my apps executable with matching 9 command line parameters then exit if there 8 is a match.
My app can run more than once, but 7 I don't want it running the same config 6 file at the same time.
Obviously, this is 5 Windows specific, but the same concept is 4 pretty easy on any *NIX system even without 3 specific libraries simply by opening the 2 shell command 'ps -ef' or a variation and 1 looking for your app.
'*************************************************************************
' Sub: CheckForProcess()
' Author: Ron Savage
' Date: 10/31/2007
'
' This routine checks for a running process of this app with the same
' command line parameters.
'*************************************************************************
Private Function CheckForProcess(ByVal processText As String) As Boolean
Dim isRunning As Boolean = False
Dim search As New ManagementObjectSearcher("SELECT * FROM Win32_process")
Dim info As ManagementObject
Dim procName As String = ""
Dim procId As String = ""
Dim procCommandLine As String = ""
For Each info In search.Get()
If (IsNothing(info.Properties("Name").Value)) Then procName = "NULL" Else procName = Split(info.Properties("Name").Value.ToString, ".")(0)
If (IsNothing(info.Properties("ProcessId").Value)) Then procId = "NULL" Else procId = info.Properties("ProcessId").Value.ToString
If (IsNothing(info.Properties("CommandLine").Value)) Then procCommandLine = "NULL" Else procCommandLine = info.Properties("CommandLine").Value.ToString
If (Not procId.Equals(Me.processId) And procName.Equals(processName) And procCommandLine.Contains(processText)) Then
isRunning = True
End If
Next
Return (isRunning)
End Function
I found a cross platform way to do this 1 using boost/interprocess/sync/named_mutex
. Please refer to this answer https://stackoverflow.com/a/42882353/4806882
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.