QSingleApplication
? QMutex
? QSharedMemory
? I'm looking for something that will work smoothly in Windows, OSX and Linux (Ubuntu). Using Qt 4.7.1
相关问题
- Sorting 3 numbers without branching [closed]
- QML: Cannot read property 'xxx' of undefin
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
相关文章
- ubuntu20.4中c#通过c++库调用python脚本
- Qt槽函数自动执行多遍
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
I am using this solution for now.
However it has the drawback that the program can only be run once by the user, even if they login from multiple locations at the same time.
singleinstance.h
singleinstance.cpp
Simple solution, that does what you want. Without network dependency (as
QtSingleApplication
) and without any overhead.Usage:
RunGuard.h
RunGuard.cpp
You can use
QSharedMemory
with a specific key and check if the shared memory with that key could be created or not. If it is nor able to create it, then an instance is already run:for Windows:
According to Qt's doc, an acquired
QSystemSemaphore
won't be automatically released if the process crashes without calling its destructor under Unix-like OSes. Which could be the cause of a deadlock in another process trying to acquire the same semaphore. If you want to be 100% sure that your program properly handles crashes and if you don't insist on using Qt, you may want to use the other locking mechanisms which the operating systems do automatically release when the process dies - for example,lockf()
and theO_EXLOCK
flag passed toopen()
which are mentioned in How do I recover a semaphore when the process that decremented it to zero crashes? orflock()
. In fact, creating of shared memory is no longer needed ifflock()
is used. Simply usingflock()
is enough to make single instance app protection.If recovering semaphore from crashes in Unix doesn't matter, I think that RunGuard from Dmitry Sazonov's answer could still be somewhat simplified:
The destructor
~RunGuard()
andRunGuard::release()
may be taken off sinceQSharedMemory
will automatically detach from the shared memory segment upon its destruction, as in Qt's doc forQSharedMemory::~QSharedMemory()
: "The destructor clears the key, which forces the shared memory object to detach from its underlying shared memory segment.".RunGuard::isAnotherRunning()
may also be taken off, too. The goal is exclusive execution. As @Nejat has mentioned, we can merely take advantage of the fact there could be at most one shared memory segment being created for a given key at any time, as in Qt's doc forQSharedMemory::create()
: "If a shared memory segment identified by the key already exists, the attach operation is not performed and false is returned."If I understand correctly, the purpose of "fix"
QSharedMemory
object in the constructor is to destroy the shared memory segment which survives due to the previous process crash, as in Qt's doc: "Unix: ... When the last thread or process that has an instance ofQSharedMemory
attached to a particular shared memory segment detaches from the segment by destroying its instance ofQSharedMemory
, the Unix kernel release the shared memory segment. But if that last thread or process crashes without running theQSharedMemory
destructor, the shared memory segment survives the crash.". When "fix" gets destructed, an implicitdetach()
should be called by its destructor and the surviving shared memory segment, if any, will be released.Not sure if
QSharedMemory
is thread-safe/process-safe or not. Otherwise, the code related tomemLock
may be further removed if thread-safety is handled internally byQSharedMemory
. On the other hand,fix
should also be protected bymemLock
if the safety is an issue:because an explicit
attach()
and an implicitdetach()
are called aroundfix
.The simplified version of
RunGuard
is as follows:Usage:
runGuard.h:
runGuard.cpp:
There is a possible race condition here:
Consider the scenario:
When the current process ProcCur runs to
(tag1)
the following happens: (note that(tag1)
is outside of lock protection)RunGuard
starts to run.(tag2)
and successfully creates the shared memory.release()
at(tag3)
.(tag1)
.(tag2)
and attempts to create shared memory. However,sharedMem.create()
will returnfalse
because ProcOther have left a created one. As we can see in the doc ofQSharedMemory::create()
: "If a shared memory segment identified by the key already exists, the attach operation is not performed and false is returned."RunGuard::tryToRun()
in ProcCur will returnfalse
, which is not as expected because ProcCur is the only existing process usingRunGuard
.As
QtSingleApplication
is relatively obsolete and not maintained anymore, I wrote a replacement, called SingleApplication.It is based on
QSharedMemory
and uses aQLocalServer
to notify the parent process of the new instance being spawn. It works on all platforms and is compatible with Qt 5.The full code and documentation are available here.