From a590e77fd8721acc0c844f86db86d5c9445fa9a6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 4 May 2011 13:02:57 +0100 Subject: Fix QNetworkConfigurationManager usage outside main thread first QNetworkConfigurationManager creates the engines loaded from plugins as objects in the main thread. If a QNetworkConfigurationManager instance is created in a worker thread without any instance previously existing in the main thread, then it is uninitialised until the main thread has run. This causes allConfigurations() to return an empty list if called immediately after instantiation, for example. This fix initialises the plugins using blocking queued connections, which causes the worker thread to block until the initialisation function has been called in the context of the main thread. Deadlock is possible if the main thread is for some reason waiting on the worker thread, but it will not deadlock on QNetworkConfigurationManager's mutex. If this is a problem for an application, it should use QNetworkConfigurationManager from the main thread first to preload the plugins. Task-number: QTBUG-18795 Task-number: QTBUG-18799 Reviewed-by: Cristiano Di Flora --- src/network/bearer/qnetworkconfigmanager_p.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/network/bearer/qnetworkconfigmanager_p.cpp') diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index e9b6703dd9..a948d917c4 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -385,8 +385,6 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer))); connect(engine, SIGNAL(configurationChanged(QNetworkConfigurationPrivatePointer)), this, SLOT(configurationChanged(QNetworkConfigurationPrivatePointer))); - - QMetaObject::invokeMethod(engine, "initialize"); } } @@ -410,8 +408,19 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() startPolling(); } - if (firstUpdate) + if (firstUpdate) { firstUpdate = false; + QList enginesToInitialize = sessionEngines; //shallow copy the list in case it is modified when we unlock mutex + Qt::ConnectionType connectionType; + if (QCoreApplicationPrivate::mainThread() == QThread::currentThread()) + connectionType = Qt::DirectConnection; + else + connectionType = Qt::BlockingQueuedConnection; + locker.unlock(); + foreach (QBearerEngine* engine, enginesToInitialize) { + QMetaObject::invokeMethod(engine, "initialize", connectionType); + } + } } void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() -- cgit v1.2.3