QCoreApplication not in "main" thread (e.g win32 service) and unfortunate behaviour difference between 5.7.0 and 5.9.0
-
For some applications - I'm talking windows services here the QCoreApplication is technically not in the main thread as this is created by windows. On porting numerous applications from 5.7 to 5.9 I observed that some of our windows service applications were not starting up correctly but all our other apps were just fine. Our windows services use our own class library developed long before we even started using Qt (and that was a long time ago) but thats entirely irrelevant. The issue appears to be very simple in principle but establishing exactly what has changed in the Qt runtime is proving to be rather more troublesome. So what is the problem... Well it seems that if during static object initialisation that if anything should so much as look at QThread::currentThread(). Just using classes like QFile, QLibrary are enough to do this then when the QCoreApplication object is subsequently created (in the service thread which we consider to be the main thread even though technically its not) subsequent access of its eventDispatcher() method will return nullptr. You will also see a qWarning emitted... qWarning("WARNING: QApplication was not created in the main() thread."); But if you manage to avoid any static object contractor calls that create things like QFile then everything is just fine and you don't get this warning. If you do get the warning and for instance create a QFileSystemWatcher later (in the same thread as QCoreApplication) then its game over as this blindly uses the eventDispatcher() to install a filter and will die of a hideous nullptr deref death! Debugging the startup of windows services is fraught with difficulties but all of our services can be run in a console debug mode and by default this uses the real main thread. In this console debug mode these programs all work just fine. I amended our console debug mode to allow call of the service main entry from a std::thread and used this to provide another debug alternative debug environment. This also shows the problem clearly. However elucidating the real cause and determining what and where the change is is really proving to be very hard indeed. I have even resorted to comparing the Qt sources (at least the ones I think likely to be involved under corelib (kernel & thread). I can only see changes here that are subtle/seemingly irrelevant and clearly must be missing the relevant change responsible for this altered behaviour!! Incidentally I started attacking our codebase and removing as many static objects as practical or delaying their creation (there were not many) but there were one or two places where it looked as though I'd end up having to rewrite things that used Qt API and replace with native win32 calls - I'd consider this to be an horrific retrograde step though and will take time and incur additional cost and retest time.
Has anyone else run into similar problems and does anyone have an explanation or suggested workaround?
-
On a more serious note,
i would ask directly on the mailing list
http://lists.qt-project.org/mailman/listinfoif nothing turn up here. There would be a good chance some of the devs would know what changed.
-
@navsystems said in QCoreApplication not in "main" thread (e.g win32 service) and unfortunate behaviour difference between 5.7.0 and 5.9.0:
I can only see changes here that are subtle/seemingly irrelevant and clearly must be missing the relevant change responsible for this altered behaviour!!
There's no changed behavior. You have been depending on an implementation detail and you got bitten. You can't create
QObject
s before you have yourQCoreApplication
created, so this excludes any staticQObject
instances.@navsystems said in QCoreApplication not in "main" thread (e.g win32 service) and unfortunate behaviour difference between 5.7.0 and 5.9.0:
Has anyone else run into similar problems and does anyone have an explanation or suggested workaround?
Don't create static
QObject
s is my best advice. I have run through similar problems while writing theQtDaemon
module (which is what you want basically - a class managing a service), and while not exactly trivial I've made the user code run in the main thread, which is also how it is on other platforms.