Mutex instances
Mutex instances
I wish to make a program that can only have one instance of the code...under C++ this can be accomplished via CreateMutex because a specific ID is used in the parameter, and if there is already a Mutex with that id then it fails...
Can this be done in FB with MutexCreate?
Thanks,
Thrawn
Can this be done in FB with MutexCreate?
Thanks,
Thrawn
mutexes are used for locking threads while another thread accesses shared resources. And why would you want to have one instance anyway?
you can do smth like:
you can do smth like:
Code: Select all
sub test ()
static init = 0
if (init > 0) exit sub
init = 1
'' do your stuff here
end sub
This works in Windows (compile, execute 2 or more instances from command line or Explorer):
See also: OpenMutex
Code: Select all
'fb v0.16 release
option explicit
#include once "windows.bi"
dim as integer res
dim as string mtn
dim as HANDLE mc
'
mtn="MyProgInst" 'your specific ID
SetLastError(0)
mc=CreateMutex(NULL,TRUE,strptr(mtn))
res=GetLastError()
print mc,res
if res=ERROR_ALREADY_EXISTS then
print "This is not the first instance of this exe (mutex=";mc;")"
else
print "First instance of this exe (mutex=";mc;")"
end if
sleep
ReleaseMutex(mc)
end
Some people do want to have a single instance program. It is recommended also in some MS documentation for stopping multiple instances, however some people disagree with this due to security implications if someone steals your unique mutex name.
Heres some code I got from one of the API help files, or from MSDN, i forget which now.
The reason for checking ERROR_ACCESS_DENIED, is because we are passing a NULL security descriptor, and will be denied access to the mutex if an other, higher level user has access.
I don't think it can be done using the FB mutex commands, as they don't allow a named mutex, but i could be wrong, i've not used them much.
Heres some writing on how it could be a potential security problem.
http://blogs.msdn.com/oldnewthing/archi ... 39479.aspx
Heres some code I got from one of the API help files, or from MSDN, i forget which now.
The reason for checking ERROR_ACCESS_DENIED, is because we are passing a NULL security descriptor, and will be denied access to the mutex if an other, higher level user has access.
I don't think it can be done using the FB mutex commands, as they don't allow a named mutex, but i could be wrong, i've not used them much.
Code: Select all
#include "windows.bi"
Option Explicit
Function IsAlreadyRunning() As Integer
Dim ret As DWORD
If CreateMutex(NULL, TRUE, "_YourProgNameMutex") <> 0 Then
ret = GetLastError()
If (ret = ERROR_ALREADY_EXISTS) OR (ret = ERROR_ACCESS_DENIED) Then
Return -1
End If
End If
Return 0
End Function
If IsAlreadyRunning Then
Print "An instance of this program is already running"
Else
Print "Hello"
End If
Sleep
End
http://blogs.msdn.com/oldnewthing/archi ... 39479.aspx
Ok then, well, I want to be able to port this over to linux, so I guess if someone clicks the icon twice, they've screwed themselves...lol, but I'll import the windows code for the win32 build I guess...
I can understand the security risk, but because it is a game, denial of the program from an attacker is not really my consern...
Plus theres a way to limit the security risk by terminating the new instance AFTER you focus the already instanced program...
I just think its better than a computer crash cause by an impatient user, which is more likey than an attacker...
Is there a way to do this on linux?
Thanks for everything,
Thrawn
I can understand the security risk, but because it is a game, denial of the program from an attacker is not really my consern...
Plus theres a way to limit the security risk by terminating the new instance AFTER you focus the already instanced program...
I just think its better than a computer crash cause by an impatient user, which is more likey than an attacker...
Is there a way to do this on linux?
Thanks for everything,
Thrawn
Just for curiosity's sake, why do you need to enforce single instance?
This is tough to do correctly on Linux, due to the fact that there can be multiple users logged in at once, multiple X sessions, multiple desktops, etc... There is no really good way without knowing why you need such a thing. (Of course, the same could be said for Windows if you consider Terminal Services, but most people aren't running Windows Server, whereas X is designed to do this sort of thing. :)
This is tough to do correctly on Linux, due to the fact that there can be multiple users logged in at once, multiple X sessions, multiple desktops, etc... There is no really good way without knowing why you need such a thing. (Of course, the same could be said for Windows if you consider Terminal Services, but most people aren't running Windows Server, whereas X is designed to do this sort of thing. :)
Its just for a game, I just think it would be bad to crash the user's computer if the user decides that "oooh, mabey if I click on the icon a few more times it'll load faster"...
But then again, those that have linux, arent the type to do that anyways, so I'll include the code on the win32 build only...kk thanks,
Thrawn
But then again, those that have linux, arent the type to do that anyways, so I'll include the code on the win32 build only...kk thanks,
Thrawn
The positives of using a global mutex in Windows are:
1. It's really simple
2. The mutex will be released if something untoward happens (program crash, sys reboot, etc)
The code below is a demo of how to use a (Windows) file locking method to detect multiple instances. This is still in effect a "global lock", not TS-friendly. Write the lock file to the user's home dir to limit one instance per user (TS-friendly). See "Notes:" at end.
Notes:
The lock created by code above will release, if not released deliberately, when the process terminates (I think even with abnormal termination). But at the whim (timing) of the OS. Probably not an issue..
This same method, but using flock() or fnctl(), can be used on *.nix - you'd have to create the lock file in /tmp to make it global. BUT (big but) I don't rem if that lock is removed if the creating/locking process terminates without removing same lock. You could also do something extremely crude like parse the proclist checking for a previous instance of your prog.
This code hasn't been tested thoroughly. Caveat emptor. Needs better (any) error checking in case file creation fails..
1. It's really simple
2. The mutex will be released if something untoward happens (program crash, sys reboot, etc)
The code below is a demo of how to use a (Windows) file locking method to detect multiple instances. This is still in effect a "global lock", not TS-friendly. Write the lock file to the user's home dir to limit one instance per user (TS-friendly). See "Notes:" at end.
Code: Select all
'lockfile for single-instance detection, Windows
' compile, execute 2 or more instances
'fb v0.16 release
option explicit
#include once "windows.bi"
declare function LockFileCheck(fname as string) as HANDLE
dim as integer res
dim as string fname
dim as HANDLE FHandle
fname=exepath + "\Zfile.lck" 'file lock location/name
FHandle=LockFileCheck(fname)
res=LockFile(FHandle,0,0,8,0)
if res=0 then
print "This is not the first instance"
'bail here..
else
print "First instance.."
end if
sleep
res=UnLockFile(FHandle,0,0,8,0)
CloseHandle(FHandle)
end
function LockFileCheck(fname as string) as HANDLE
dim as integer pcount,res
dim tbuff as string
dim as HANDLE FHandle
SetLastError(0)
FHandle = CreateFile(fname, _
GENERIC_WRITE, _
FILE_SHARE_WRITE, _
NULL, _
OPEN_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
NULL)
if GetLastError=0 then 'file didn't exist..
tbuff="LockFile"
res=WriteFile(FHandle,_
strptr(tbuff),_
len(tbuff),_
@pcount,_
NULL)
CloseHandle(FHandle)
'print "File created"
LockFileCheck(fname) 'reopen to get handle
end if
return FHandle
end function
The lock created by code above will release, if not released deliberately, when the process terminates (I think even with abnormal termination). But at the whim (timing) of the OS. Probably not an issue..
This same method, but using flock() or fnctl(), can be used on *.nix - you'd have to create the lock file in /tmp to make it global. BUT (big but) I don't rem if that lock is removed if the creating/locking process terminates without removing same lock. You could also do something extremely crude like parse the proclist checking for a previous instance of your prog.
This code hasn't been tested thoroughly. Caveat emptor. Needs better (any) error checking in case file creation fails..