2

That's the problem: I don't like multiple instances of my program, that's why I've disabled them. My program opens a specific mime-type. In my system (Ubuntu 12.04), when I double click one of these files, this is executed:

/usr/bin/myprogram /path/to/double/clicked/file.myextension

As I said, I don't like multiple instances, so, if the program is already running and the user chooses to open one of these files, a DBus message is being sent to the already instance so as to take care the opened file. So, if there's an already running instance and the user choose 3 files to open with my program and hit the [Enter] button, the system executes:

/usr/bin/myprogram /path/to/double/clicked/file1.myextension
/usr/bin/myprogram /path/to/double/clicked/file2.myextension
/usr/bin/myprogram /path/to/double/clicked/file3.myextension

All of these instances detect the already running instance and sent the opened file to it. No problems at all, till now.

But, what if there isn't an already running instance and the user chooses to open 3 files altogether with my program? The system will call concurrently, again:

/usr/bin/myprogram /path/to/double/clicked/file1.myextension
/usr/bin/myprogram /path/to/double/clicked/file2.myextension
/usr/bin/myprogram /path/to/double/clicked/file3.myextension

and each of these instances will realize that there's an already running instance, it will try to sent a DBus message to the already running instance and it will exit. So, all the 3 processes will do the same thing and nothing will run.

How can I avoid this problem?

PS: In order to detect if there are already running instances I implement the following code:

bool already_runs(){
return !system("pidof myprogram | grep \" \" > /dev/null");
}
hytromo
  • 1,501
  • 2
  • 27
  • 57
  • When opening multiple files, shouldn't it pass all three paths to one command? E.g. /usr/bin/myprogram file1 file2 file3 – Alan Jul 24 '12 at 14:16
  • @Alan: whether it does or it doesn't, there's still at least the possibility that someone could run the program three times in quick succession by some other means :-) What's needed is a way for one of the copies of the program to declare itself the "first one". For example this could be by acquiring a lock on a particular file, but I don't know QT, and that would be a rubbish answer if QT provides some mechanism to help. – Steve Jessop Jul 24 '12 at 14:26
  • You need to detect not just that another instance is running, but that there's a running instance which has accepted that it is the one instance. – bames53 Jul 24 '12 at 14:42
  • @Alan, I know, I've though about this, and my program can handle it this way (It can handle as arguments: myprogram file1 file2 file3 etc), but the system calls 3 different times my program – hytromo Jul 24 '12 at 15:25

2 Answers2

0

I would use some shared memory to store the pid of the first process. The QSharedMemory class will help you here.

The first thing your program should do is try to create a shared memory segment (using your own made up key) and store your pid inside it. If the create call fails, then you can try to attach to the segment instead. If that succeeds then you can read the pid of the original process from it.

EDIT: also, remomber to use lock() before writing to or reading from the shared memory, and then call unlock() when you are done.

Alan
  • 1,895
  • 1
  • 10
  • 9
  • The link doesn't work anymore, here's the [Qt 4.8 reference for QSharedMemory](http://doc.qt.io/qt-4.8/qsharedmemory.html) and the [Qt 5.5 reference for QSharedMemory](http://doc.qt.io/qt-5/qsharedmemory.html). – basic6 Oct 24 '15 at 21:53
0

The standard way to do this in DBus is to acquire your application's name on the bus; one instance will win the race and can become the running instance.

However, you should be able to do this using Qt functionality which will integrate better with the rest of your application; see Qt: Best practice for a single instance app protection.

Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366