Tuesday, June 21, 2011

Qt5 & a major update for QtService - QDaemonApplication

In May I proposed that QtService be integrated natively into Qt5 [1], and I offered to spearhead that task [6] and support Windows and Linux (Embedded and X11)[6]. In June I setup a branch of the Qt5 master repository[10] for supporting this task (I'll likely need to rebase it), and am working to get up to speed on using git (I have primarily used SVN), so I expect that getting going will be a little slow in that respect. (Sadly, a bit slower than anticipated. I am working on it.)

All that said, below is the summary from the Qt5-Feedback mailing list covering naming conversations, etc; and some additional stuff as I have contemplated that. The discussion has been very good thus far, but has made keeping track of via e-mail a little hard – so I am looking for a nice Wiki home for it all. I'll put it there once I find a nice home (probably at the Qt Dev Wikis somewhere) and get a chance to repost it here.

In the mean-time, please feel free to leave comments below.


QtService is presently an add-on provided by Trolltech/Nokia through the Qt Components system [1]. However, for a variety of reasons it is desirable by myself and others that it be a native part of Qt [1,3] whether as part of Qt Core or a module provided with Qt itself [1, 9]. In either case, it needs some TLC to bring it up to date as well as some improvements. To start, the existing QtService implementation is a C++ Template-based implementation[1,3]; the end result is that this prohibits use of signals/slots internally to the QtService code [1,3], prevents the ability to do a scheduled, orderly shutdown [1], and makes it hard to work with the command-line [3,5].

It has been proposed to make a new QtService implementation that makes use of C++ Abstract Interface classes instead [1,3]. In the process of doing so the ability to derive an interactive service will be removed per encouraging best practices and that it will not work on all platforms [1,3]. The new implementation should likely use a different name - e.g. QService, QDaemon, or QDaemonService - to be more consistent with existing names of parallel functionality - e.g. QCoreApplication, QApplication [5], and should address issues in the command-line [3,5], communication between controller and service [5], and add the ability to do controller shutdowns of the service [1].


I originally called for the work to be integrated into Qt Core.[11] However, after fleshing out further details we revealed several dependencies on modules – Qt SWF, Qt Network, and others. That is not to say that Qt SFW and this may not end up in the same module, but it will at least be in a separate module. For the time being, I am calling the new module QtService with the intention that Qt SFW be able to share it (more below).


I originally proposed to use the name QDaemonService.[11] Some thought this was too long and it was proposed to just use QService.[14] However, it was pointed out the Qt SFW already uses this QService* namespace.[20,22] So, we will use the QDaemon* namespace instead to minimize confusion in the API.


QDaemonApplication will be a formal object like QApplication and QCoreApplication, and should set up the application environment in a similar manner. That is, the command-line options provided should be available via calling QCoreApplication::arguments(). It should also have a function to tell the program whether it is the formal service or the controller so that developers can interact in both modes - thus being able to interact with the command-line as necessary.

In keeping with the naming conversions mentioned previously [5,11] the primary interface class with be QDaemonApplication. Thus the main application will look something like the following:


    int main(int argc, char* argv[]) {
        QDaemonApplication service(argc,argv);
        return service.exec();

Back-End Communications:

In the QtService component, the service code used network connections under *nix and the Win32 Service Manager API on Windows for communication, which primarily relies on some IPC and command-line stuff to communicate. I think it is very important that each platform integrate something native to do the communications. To that end, I believe Qt SFW likely provides the best method of providing that functionality, and think we should collaborate between the two to utilize the IPC portion. Windows support will still require using the Win32 Service Manager API at least on the front end, and may in the back-end too so there may be some additional options of that nature. But primarily, I think we can rely on Qt SFW for IPC functionality – to provide integration for IPC, D-Bus, Shared Memory, etc – whatever is best for the platform and do so via a configurability during compile or (even better) at run-time. Otherwise, I fear we may reinvent the wheel that another portion of Qt has already finished – so why do it twice when the functionality is already there? (Yes, I realize Qt SFW was not available in Qt4 so readily. But from what I understand it will be in Qt5.)

This functionality will be hidden by the QDaemonApplication class. Developers utilizing these classes should not have to be concerned about the back-end communications – it should just work from their perspective.

Front-End Interfaces:

In the QtService component, the service code used the command-line as the sole front-end interface. However, QDaemon* should integrate with various systems, as well as keeping that simplistic command-line interface. So, while the command-line interface will be the first-out-of-the-gate supported front end, we should also add configuration support (likely build-time only) for supporting other mechanisms – e.g. systemd, zeroconf, upstart, bonjour, launchpad, etc. Once we have moved beyond supporting solely the command-line then native mechanisms will be set to be the defaults for each platform when such functionality is available (e.g. launchpad on Mac). In the case where there may be several different mechanisms (e.g. Linux – systemd, zeroconf, command-line, D-Bus, etc.) then we may select an appropriate default – e.g. D-Bus or command-line for Linux.

The primary idea here is that since there are so many different front-ends for driving service/daemon applications, it should be configurable with appropriate defaults selected. It should be as easy as possible to enable integration of new front-end interfaces for future expansion.

This functionality will be hidden by the QDaemonApplication class.

Developer Interaction:

As the application will daemonize itself in the QDaemonApplication object, developers will need to have an interface object with that class. To this extent, Developers will be required to create a class derived from an abstract interface class – QAbstractDaemonObject – which is then registered in some manner (function/signal/slot) with the primary QDaemonApplication object.

Class Architecture:

The QDaemon* namespace will consist of two public classes:


And a number of internal classes to provide the various mechanisms for setting up the environment, interacting with the front-end APIs, etc.

The primary purpose of QAbstractDaemonObject will be to provide sufficient interfaces for developers to utilize both pre-demonization and post-daemonization. The QDaemonApplication object will do most of the work in bringing up the application, however, it will not daemonize the application until the exec() function is called – thus providing the developer time to interact with the pre-daemonized process. By allowing the developer to derive from this interface, we can also provide sufficient means to enable communications for the developer between the pre-daemonized and post-daemonized process – for custom communications (likely serializing to and deserializing from a QByteArray) via standardized signals/slots.


Some platforms (e.g. Windows) only allow a single instance (primarily determined by the installation location and name of the service as registered with the Win32 Service Manager API) of a service to operate at a time. Other platforms could care less. To this degree, QDaemonApplication should contain the ability to differentiate between platforms and inform the developer if it is allowed, and if it is provide the developer with an easy means (boolean option) on whether to allow it or not.[14]

I think that's enough to get some discussion going.

[1] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000246.html
[2] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000247.html
[3] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000253.html
[4] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000256.html
[5] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000259.html
[6] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000262.html
[7] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000266.html
[8] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000267.html
[9] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-May/000264.html
[10] https://gitorious.org/~benjamenmeyer/qt/brm-qt5-service
[11] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000449.html
[12] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000450.html
[13] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000453.html
[14] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000454.html
[15] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000455.html
[16] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000457.html
[17] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000459.html
[18] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000460.html
[19] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000461.html
[20] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000463.html
[21] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000478.html
[22] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000500.html
[23] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000525.html