diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2021-04-13 17:01:38 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2021-04-14 10:47:20 +0200 |
commit | e875c071ec32ab9aa460c982f25f6c6191e41326 (patch) | |
tree | 4c2a3e4bf9a301f0a906a0f74ae230b78093b294 /src/network/kernel | |
parent | d61dc9a8cda2e3f3c3eb91283af71e9cd5044fd8 (diff) |
QNetworkInformation: delete the instance as a post-routine
On Windows, on exit, the backend will deref (and then implicitly start
deletion of) a COM object. This object tries to communicate with an
object in another thread, though it seems this other thread quits before
the main thread in _most_ cases.
To get around this we move the deletion to earlier in the program. While
this is only reported as a Windows issue it makes for more consistent
behavior if all platforms behave the same.
Document and test that recreation of QNI works as expected after the
destruction (and recreation) of QCoreApplication.
Amends: 0875626e22ad4e709ddf505e701a8d699559f5b4
Fixes: QTBUG-92568
Pick-to: 6.1 6.1.0
Change-Id: Iffc07f38673019aa059efd4d64d2ad706a03f6fe
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src/network/kernel')
-rw-r--r-- | src/network/kernel/qnetworkinformation.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/network/kernel/qnetworkinformation.cpp b/src/network/kernel/qnetworkinformation.cpp index 6ce572d408..c36b1c4698 100644 --- a/src/network/kernel/qnetworkinformation.cpp +++ b/src/network/kernel/qnetworkinformation.cpp @@ -46,6 +46,7 @@ #include <QtCore/private/qobject_p.h> #include <QtCore/qcoreapplication.h> #include <QtCore/qmutex.h> +#include <QtCore/qthread.h> #include <QtCore/private/qfactoryloader_p.h> #include <algorithm> @@ -73,11 +74,30 @@ struct QStaticNetworkInformationDataHolder }; Q_GLOBAL_STATIC(QStaticNetworkInformationDataHolder, dataHolder); +static void networkInfoCleanup() +{ + if (!dataHolder.exists()) + return; + QMutexLocker locker(&dataHolder->instanceMutex); + QNetworkInformation *instance = dataHolder->instanceHolder.get(); + if (!instance) + return; + + auto needsReinvoke = instance->thread() && instance->thread() != QThread::currentThread(); + if (needsReinvoke) { + QMetaObject::invokeMethod(dataHolder->instanceHolder.get(), []() { networkInfoCleanup(); }); + return; + } + dataHolder->instanceHolder.reset(); +} + class QNetworkInformationPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QNetworkInformation) public: - QNetworkInformationPrivate(QNetworkInformationBackend *backend) : backend(backend) { } + QNetworkInformationPrivate(QNetworkInformationBackend *backend) : backend(backend) { + qAddPostRoutine(&networkInfoCleanup); + } static QNetworkInformation *create(QNetworkInformation::Features features); static QNetworkInformation *create(QStringView name); @@ -408,7 +428,9 @@ QNetworkInformationBackendFactory::~QNetworkInformationBackendFactory() you can load() plugins based on which features are needed. QNetworkInformation is a singleton and stays alive from the first - successful load() until application shutdown. + successful load() until destruction of the QCoreApplication object. + If you destroy and re-create the QCoreApplication object you must call + load() again. \sa QNetworkInformation::Feature */ |