PDA

View Full Version : Limiting the number of instances of one application



fullmetalcoder
11th October 2006, 09:07
I'm trying to limit the number of running instances of an application, which is mostly useful when dealing with file registration...

I've had a quick look at Assistant which seems to use a client/server architecture to achieve that (through QTcpSocket if I remember well) and I didn't understand how it worked... Any explanation ?

e8johan
11th October 2006, 09:17
There is a Qt solution for this... and KDE does it (I seem to recall). Perhaps you can find simple solutions there...

Mike
11th October 2006, 10:11
Well you could use a computer resource like a socket - you suggested that already. Pick a range of e.g. 5 sockets that your app would try to open. maybe 40000...40004. When your app is starting it will try to open such a socket. If it fails it will open the next in that range. If no socket in that range is available then your app would not start. Maybe you even enhance the socket logic that way, that you can send a simple command to it and wait for a known response. If that response doesn't come, then you know it's not your app, but the app from somebody else...
Does this make sense?
If sockets is not what you want to use, you may create something else like a named message queue or pipe... or a kernel mutex etc... there are several solutions to this...

Valheru
11th October 2006, 14:26
Isn't this what DCOP is for in KDE? Don't know what Windows uses or if Qt has it's own abstraction for handling stuff like this.

fullmetalcoder
13th October 2006, 08:15
Well you could use a computer resource like a socket - you suggested that already. Pick a range of e.g. 5 sockets that your app would try to open. maybe 40000...40004. When your app is starting it will try to open such a socket. If it fails it will open the next in that range. If no socket in that range is available then your app would not start. Maybe you even enhance the socket logic that way, that you can send a simple command to it and wait for a known response. If that response doesn't come, then you know it's not your app, but the app from somebody else...
Does this make sense?
If sockets is not what you want to use, you may create something else like a named message queue or pipe... or a kernel mutex etc... there are several solutions to this...
There are two problems : I don't have any experience of socket programming and I want a cross-platform solution.
Moreover I don't think I have enough time to search for that feature into the whole KDE sources and then port that Qt3 (and maybe KDE kernel)-dependent code to plain and portable Qt4.
You talked about "socket ranges", could you explain that to me alittle deeper? As I said I'm a noob in socket-programming...:o

nouknouk
13th October 2006, 09:34
Hi,

for registered customers, there is a special class to ensure only one instance of your application is running : QtSingleApplication (it exists for both Qt3 and Qt4 versions).

This class is unfortunately unavailable for open-source licensee :-/

fullmetalcoder
13th October 2006, 12:49
This class is unfortunately unavailable for open-source licensee :-/
Unfortunately my software is meant to be Open Source thus compilable against Qt Open source so I can't rely on something like this. Neither can I "steal" its code so I'm looking for an equivalent solution in plain cross-platform and open source Qt 4. If you've heard about this class maybe you could explain me roughly how it works???

gfunk
13th October 2006, 18:33
My guess is that their QtSingleApplication would do something different for each OS, as there's nothing preventing Qt from doing whatever it wants, as long as it achieves the "single app" functionality. In Windows, it can be fairly easily done with their own named pipes or named mutexes (not an option for other os's) - I'm sure other OS's have their own efficient way of accomplishing the "single app".

Using sockets not be very elegant as it pollutes the port number-space, and in the worst case, may have to check several port numbers - but for the end-user, it may still be suitable and sufficiently portable.

nouknouk
14th October 2006, 09:21
Hi,

about general concepts of QtSingleApplication, there are 3 different ways the mutex is implemented, depending on the OS used (Win, MacOS, Linux) :

-on windows, the CreateMutex function is used, the time a call to FindWindow is done. If the window is already existing, that means an instance is already started. The mutex is released just after in all cases.

- on linux, the Atom feature is used to implement the mutex. The window is then retrieved with something like findWindow

- on mac ... i don't know ;)

QtsingleApplication gives another feature : the ability to send a message to the already running instance. Usefull, for example, when the second application's instance wants to send a filename to the first one in order to open a document. This mechanism is implemented using platform specific ways to post a message in their event loops.

fullmetalcoder
14th October 2006, 16:35
Are "regular" Qt mutexes/threads/... able to perform this task or am I forced to use plenty of dirty platform-dependent code (which I don't know well BTW)?

@nouknouk : you seem to be quite informed about QtSingleAppication. Do you think Trolltech plans to release it under GPL?

Chicken Blood Machine
15th October 2006, 02:05
A quick and dirty cross-platform solution would be to create a 'lock' file at startup and delete the file at shutdown. Any new instances check if the file exists first before continuing.

This isn't foolproof, since if your app crashes, you will have to delete the file manually.

wysota
15th October 2006, 11:05
This isn't foolproof, since if your app crashes, you will have to delete the file manually.

You can overcome that problem for example by checking if a process which created the file exists (the file can contain the process id of the creator). This still isn't 100% sure, but improves the situation a little.

fullmetalcoder
16th October 2006, 07:23
I know I can use process ID under Unix platform but what about others, especially Windows? Actually, even if it's not the most straightforward I think the sockect stuff is the best... I'll try to understand designerassistant sources and, well, we'll see...

wysota
16th October 2006, 07:34
I know I can use process ID under Unix platform but what about others, especially Windows?
I'm sure there is something like a process id on Windows as well.


Actually, even if it's not the most straightforward I think the sockect stuff is the best... I'll try to understand designerassistant sources and, well, we'll see...
What if some other process is already using those sockets? It might be impossible to start even a single instance of the application. Probably the proper way to go would be to use semaphores and/or shared memory. It's just a few lines of platform dependent code.

nouknouk
16th October 2006, 16:32
@nouknouk : you seem to be quite informed about QtSingleAppication. Do you think Trolltech plans to release it under GPL?

I only have a licensee version of Qt, nothing more. QtSingleApplication class exists since a while (before Qt 3.3.x) and it is still not licensed under GPL, so I think It won't be available for open source license soon :/


Actually, even if it's not the most straightforward I think the sockect stuff is the best... I'll try to understand designerassistant sources and, well, we'll see...
Another issue with the use of QSocket is that the user may have a firewall that doesn't allow to open listening socket.

Chicken Blood Machine
16th October 2006, 17:17
I know I can use process ID under Unix platform but what about others, especially Windows? Actually, even if it's not the most straightforward I think the sockect stuff is the best... I'll try to understand designerassistant sources and, well, we'll see...

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getcurrentprocessid.asp

jpn
16th October 2006, 17:39
Someone recently came up with this kind of solution (http://qtnode.net/pastebin/1418) on X11.

wysota
16th October 2006, 18:29
Of course the drawback is that once the application holding the semaphore crashes, you have no way of starting it again but reboot ;)

fullmetalcoder
17th October 2006, 08:51
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getcurrentprocessid.asp
It's good to obtain a process ID (even though I'm pretty sure it can be done in plain Qt4) but what is important is to check that a proccess with this ID is running, as suggested...


Someone recently came up with this kind of solution (http://qtnode.net/pastebin/1418) on X11.
It uses something called "semaphore". Honestly I have no idea of what it is but I know that ther is a class called QSemaphore in Qt4, maybe it would fit...

wysota
17th October 2006, 11:01
It uses something called "semaphore". Honestly I have no idea of what it is
http://en.wikipedia.org/wiki/Semaphore_(programming)



but I know that ther is a class called QSemaphore in Qt4, maybe it would fit...
It wouldn't. QSemaphore works in scope of the application, whereas the above mentioned semaphores are system-wide and are therefore suited for IPC (Inter Process Communication) which is the basic idea of using them in this situation.

Trust me, you won't manage to do it in a system independent way - under the hood there is always platform specific code - even in Qt itself.

fullmetalcoder
19th October 2006, 07:54
Trust me, you won't manage to do it in a system independent way - under the hood there is always platform specific code - even in Qt itself.
Actually QTcpSocket works quite well. I've tried a few things and right now by mixing sockets, kinda lock file and a QSemaphore I'm able to prevent the creation of more than a given number of application instance. The only problem left is that communication with the working instances is not really straightforward and, ATM, buggy.

Mike
19th October 2006, 08:26
Did you also look at the QUdpSocket? (Qt Broadcast example)
Maybe it would also work this way:
1) Application is started.
2) Application opens a Udp port that is known to all applications.
3) The new app sends out a datagramm
4) Now the app does listen for all responses from other running applications
5) The new app does verify the number of responses and determines the total number of running instances
6.1) If there are too many applications running, the new app terminates itself.
6.2) If it is possible to start another instance, then the new app will close the Udp server socket and open a Udp client socket, listening for broadcast messages itself.

This should really work on any platform.

wysota
19th October 2006, 10:28
It may work but is still an ugly solution. If you only want to make sure you have a single instance of the application, you can avoid sockets. If you want your applications on a local machine to communicate, you could come up with a better solution too. Depending on high-numbered sockets is a risk, because there is no way telling if no other app (for example some ftp client or server) doesn't use the same socket.

Why do you need a QSemaphore here? Is your app accessing the socket from multiple threads?

fullmetalcoder
20th October 2006, 08:05
It may work but is still an ugly solution. If you only want to make sure you have a single instance of the application, you can avoid sockets. If you want your applications on a local machine to communicate, you could come up with a better solution too. Depending on high-numbered sockets is a risk, because there is no way telling if no other app (for example some ftp client or server) doesn't use the same socket.
Maybe ugly but better than nothing. Besides socket corruption is highly improbable since localhost is used and the port is dynamically assigned by Qt through the server classes (QTcpServer or QUdpServer)



Why do you need a QSemaphore here? Is your app accessing the socket from multiple threads?
The semaphore was just used as a convinient counter providing possibilities of extension to multithreaded approach...

arnaiz
20th October 2006, 20:12
A quick and dirty cross-platform solution would be to create a 'lock' file at startup and delete the file at shutdown. Any new instances check if the file exists first before continuing.

This isn't foolproof, since if your app crashes, you will have to delete the file manually.

IMO this is the best solution, easy and clean. It works for all platforms, it can be instrumented through the net, or locally, it can be a counter to limit number of applications...

Simple is, in many cases, the best solution...

wysota
20th October 2006, 22:50
Simple is, in many cases, the best solution...

It has its strong disadvantages. There is really no way telling if the lock file is stale or not. Under Windows you can easily use a file to make a singleton application by demanding a mandatory lock on the file. On the other hand I don't know if the lock will be released when the app gets killed. So a solution is easy but the drawback is that you might not be able to restart the application after a crash. The same goes with files holding pids of processes. You can never be sure if the lock file is stale or not and eventually you have to guess (for example by trying to find the process in the process table) or ask the user (like for example kmail does). So simple is easy to implement, but can fail as easily.

fullmetalcoder
23rd October 2006, 15:29
Mixing kinda lock file and TCP connection is definitely the best slution IMO. I'm attaching the source I've come to. It can lock the application to whatever number of instances wanted and can send messages to the first created instances (this is a limitation I didn't managed to fix with the current design so I'm working on a new version...)

Well actually I can't attach my file (too much already attached by me on other posts : I'm waiting for an answer from the admins and will attach it ASAP :o )

Lawand
11th May 2009, 09:25
I only have a licensee version of Qt, nothing more. QtSingleApplication class exists since a while (before Qt 3.3.x) and it is still not licensed under GPL, so I think It won't be available for open source license soon :/

FWIW, QtSingleApplication is now available as an Open Source Edition (LGPL) here (http://www.qtsoftware.com/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication)

TheRonin
11th May 2009, 10:29
IMHO... When I've had to limit the number of application instances in the past, I've used the port-method. With Qt it's simple to do as well. Granted, there are some problems like, what happens if another app is already using the requested port, etc. But i believe that handling those issues are simpler than creating platform specific code for locking processes or handling lock files (which in the worst case can require one or more monitoring processes to clean up after crashes etc).

Those are just my two cents, for whatever they're worth :)

roxton
16th May 2009, 14:53
Try the SingleApplication library:
http://www.qt-apps.org/content/show.php/SingleApplication?content=81163