Make the bearer QFactoryLoader a member variable, not a static

Because it was a function-level static, the QFactoryLoader was getting
destroyed out-of-sync with the bearer thread stopping. Under normal
conditions, the thread stopped first (~QApplication / ~QCoreApplication
via qAddPostRoutine), and the static got destroyed when the process
exited. However, if QApplication leaked or if the destruction order is
wonky (as seen in PyQt5), the thread could still be running when the
plugins were already unloaded.

With the loader a member variable, it gets destroyed when the thread
stops.

Note: in Qt 5.7, QFactoryLoader no longer unloads the plugins (since
commit 494376f980), so this crash cannot
happen in that version.

[ChangeLog][QtNetwork][Bearer management] Fixed a bug that could cause a
crash on application exit, depending on the order of destruction of the
QCoreApplication object and the QtDBus manager thread.

Task-number: QTBUG-56228
Task-number: QTBUG-52988
Change-Id: I33dc971f005a4848bb8ffffd147853376f82de2a
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Thiago Macieira 2016-09-27 16:52:55 -07:00
parent c7b0f56fb1
commit 7c402ad3d1
2 changed files with 5 additions and 4 deletions

View File

@ -40,8 +40,6 @@
#include "qnetworkconfigmanager_p.h"
#include "qbearerplugin_p.h"
#include <QtCore/private/qfactoryloader_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
#include <QtCore/qstringlist.h>
@ -60,7 +58,9 @@
QT_BEGIN_NAMESPACE
QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
: QObject(), pollTimer(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
: QObject(), pollTimer(0), mutex(QMutex::Recursive),
loader(QBearerEngineFactoryInterface_iid, QLatin1String("/bearer")),
forcedPolling(0), firstUpdate(true)
{
qRegisterMetaType<QNetworkConfiguration>();
qRegisterMetaType<QNetworkConfigurationPrivatePointer>();
@ -365,7 +365,6 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
bool envOK = false;
const int skipGeneric = qEnvironmentVariableIntValue("QT_EXCLUDE_GENERIC_BEARER", &envOK);
QBearerEngine *generic = 0;
static QFactoryLoader loader(QBearerEngineFactoryInterface_iid, QLatin1String("/bearer"));
QFactoryLoader *l = &loader;
const PluginKeyMap keyMap = l->keyMap();
const PluginKeyMapConstIterator cend = keyMap.constEnd();

View File

@ -55,6 +55,7 @@
#include "qnetworkconfigmanager.h"
#include "qnetworkconfiguration_p.h"
#include <QtCore/private/qfactoryloader_p.h>
#include <QtCore/qmutex.h>
#include <QtCore/qset.h>
@ -118,6 +119,7 @@ private:
private:
mutable QMutex mutex;
QFactoryLoader loader;
QList<QBearerEngine *> sessionEngines;
QSet<QString> onlineConfigurations;