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 --- .../tst_qnetworkconfigurationmanager.cpp | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp') diff --git a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp index 7787608485..33595339f2 100644 --- a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp +++ b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp @@ -62,6 +62,7 @@ public slots: void cleanup(); private slots: + void usedInThread(); // this test must be first, or it will falsely pass void allConfigurations(); void defaultConfiguration(); void configurationFromIdentifier(); @@ -329,6 +330,43 @@ void tst_QNetworkConfigurationManager::configurationFromIdentifier() QVERIFY(!invalid.isValid()); } +class QNCMTestThread : public QThread +{ +protected: + virtual void run() + { + QNetworkConfigurationManager manager; + preScanConfigs = manager.allConfigurations(); + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + configs = manager.allConfigurations(); + } +public: + QList configs; + QList preScanConfigs; +}; + +// regression test for QTBUG-18795 +void tst_QNetworkConfigurationManager::usedInThread() +{ + QNCMTestThread thread; + connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + thread.start(); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(thread.isFinished()); + qDebug() << "prescan:" << thread.preScanConfigs.count(); + qDebug() << "postscan:" << thread.configs.count(); + + QNetworkConfigurationManager manager; + QList preScanConfigs = manager.allConfigurations(); + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + QList configs = manager.allConfigurations(); + QCOMPARE(thread.configs, configs); + QCOMPARE(thread.preScanConfigs, preScanConfigs); +} QTEST_MAIN(tst_QNetworkConfigurationManager) #include "tst_qnetworkconfigurationmanager.moc" -- cgit v1.2.3 From 939886720920f907884b8b32bf501354ed805857 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 5 May 2011 13:53:17 +0100 Subject: Skip test on MacOS due to problems with corewlan plugin Reviewed-by: Cristiano di Flora --- .../tst_qnetworkconfigurationmanager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp') diff --git a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp index 33595339f2..c270eb8813 100644 --- a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp +++ b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp @@ -350,10 +350,13 @@ public: // regression test for QTBUG-18795 void tst_QNetworkConfigurationManager::usedInThread() { +#if defined Q_OS_MAC && !defined (QT_NO_COREWLAN) + QSKIP("QTBUG-19070 Mac CoreWlan plugin is broken", SkipAll); +#else QNCMTestThread thread; connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); thread.start(); - QTestEventLoop::instance().enterLoop(5); + QTestEventLoop::instance().enterLoop(100); //QTRY_VERIFY could take ~90 seconds to time out in the thread QVERIFY(thread.isFinished()); qDebug() << "prescan:" << thread.preScanConfigs.count(); qDebug() << "postscan:" << thread.configs.count(); @@ -366,6 +369,7 @@ void tst_QNetworkConfigurationManager::usedInThread() QList configs = manager.allConfigurations(); QCOMPARE(thread.configs, configs); QCOMPARE(thread.preScanConfigs, preScanConfigs); +#endif } QTEST_MAIN(tst_QNetworkConfigurationManager) -- cgit v1.2.3