QNetworkInformation: Revise locking during creation

Potential issue caught by the Mårten static analyzer.
In case another thread somehow ended up creating and returning
an instance while another was waiting to relock it would deallocate
the previous instance, which could lead to some bad situations.

Change-Id: I6e1843f8a483b2c3e0540e998c383e41f59c8655
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit c98e92b8ca7fd295482ee99f095c220b6f389169)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Mårten Nordheim 2021-02-17 09:54:48 +01:00 committed by Qt Cherry-pick Bot
parent 933162c445
commit b9a721eaaa

View File

@ -168,22 +168,21 @@ QNetworkInformation *QNetworkInformationPrivate::create(QStringView name)
{
if (!dataHolder())
return nullptr;
QMutexLocker locker(&dataHolder->instanceMutex);
#ifdef DEBUG_LOADING
qDebug().nospace() << "create() called with name=\"" << name
<< "\". instanceHolder initialized? " << !!dataHolder->instanceHolder;
#endif
if (dataHolder->instanceHolder)
return dataHolder->instanceHolder.get();
locker.unlock();
if (!initializeList()) {
#ifdef DEBUG_LOADING
qDebug("Failed to initialize list, returning.");
#endif
return nullptr;
}
locker.relock();
QMutexLocker locker(&dataHolder->instanceMutex);
if (dataHolder->instanceHolder)
return dataHolder->instanceHolder.get();
QNetworkInformationBackend *backend = nullptr;
if (!name.isEmpty()) {
@ -231,24 +230,22 @@ QNetworkInformation *QNetworkInformationPrivate::create(QNetworkInformation::Fea
{
if (!dataHolder())
return nullptr;
QMutexLocker locker(&dataHolder->instanceMutex);
#ifdef DEBUG_LOADING
qDebug().nospace() << "create() called with features=\"" << features
<< "\". instanceHolder initialized? " << !!dataHolder->instanceHolder;
#endif
if (dataHolder->instanceHolder)
return dataHolder->instanceHolder.get();
if (features == 0)
return nullptr;
locker.unlock();
if (!initializeList()) {
#ifdef DEBUG_LOADING
qDebug("Failed to initialize list, returning.");
#endif
return nullptr;
}
locker.relock();
QMutexLocker locker(&dataHolder->instanceMutex);
if (dataHolder->instanceHolder)
return dataHolder->instanceHolder.get();
const auto supportsRequestedFeatures = [features](QNetworkInformationBackendFactory *factory) {
return factory && (factory->featuresSupported() & features) == features;