News

15th October 2015 by aegeuana_sjp_admin

How to run a single app instance in QT

Sometimes we don’t want to allow users to run multiple instances of the app at once. We might want to do it, to prevent memory leak, files corruption or we decided there is no practical need to run two instances of our app at once. As there is many ways of completing this task, there is many tricky use cases as well where the single instance lock may fall.
I will show couple of cases how to implement this kind of secure lock and will describe advantages and disadvantages of each method.

Please note each occurrence of `<unique identifier>’ should be replaced by some kind of unique identifier, for example UUID.

1. Using `QLockFile` to create a lock file

This solution is good if we want to check for multiple instances running for each user. The lock file is created in a temporary directory that is specific to a logged in user. This means that each user on the system will be able to run one instance of the app for it’s own.
There is no danger when the app crashes, because the lock will be destroyed with the app instance.
[code language=”cpp”]
#include <QString>
#include <QLockFile>
#include <QDir>
#include <QMessageBox>
QString tmpDir = QDir::tempPath();
QLockFile lockFile(tmpDir + "/<unique identifier>.lock");
if(!lockFile.tryLock(100)){
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText("You already have this app running."
"rnOnly one instance is allowed.");
msgBox.exec();
return 1;
}
[/code]

2. Using `QSystemSemaphore` and `QSharedMemory` to create shared memory cluster

As the previous solution is nice and clean, sometimes we want to limit to one instance for the whole machine. It’s impossible to do with the shared lock file as there might be some permission issues. To be sure that our app will run as single instance machine wise we need to use shared memory that is common for all users. This is a bit more complicated solution, as the shared memory is common for all system users we need to be sure only one user can access it at the same time. To ensure that system semaphores are coming with help. By using system semaphores we can ensure the given part of code and shared memory will be used by single instance at the same time.
[code language=”cpp”]
QSystemSemaphore sema("<unique identifier>", 1);
sema.acquire();
#ifndef Q_OS_WIN32
// on linux/unix shared memory is not freed upon crash
// so if there is any trash from previous instance, clean it
QSharedMemory nix_fix_shmem("<unique identifier 2>");
if(nix_fix_shmem.attach()){
nix_fix_shmem.detach();
}
#endif
QSharedMemory shmem("<unique identifier 2>");
bool is_running;
if (shmem.attach()){
is_running = true;
}else{
shmem.create(1);
is_running = false;
}
sema.release();
if(is_running){
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText("You already have this app running."
"rnOnly one instance is allowed.");
msgBox.exec();
return 1;
}
[/code]
There are many more ways of ensuring single instance run on the machine, however I find these the most agile, simple and universal.

Leave a Reply

Your email address will not be published. Required fields are marked *