summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-10-06 14:40:34 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-10-06 16:13:26 (GMT)
commit7e662f3727e7c3dd3c41c29ed49bc41d2b66c744 (patch)
treeb317cd719656cb7d2dca1ea0128b4a4a63ded90a /src/network/access
parent51ed77637a6001f66805e8091ce8616d8f2530db (diff)
downloadQt-7e662f3727e7c3dd3c41c29ed49bc41d2b66c744.zip
Qt-7e662f3727e7c3dd3c41c29ed49bc41d2b66c744.tar.gz
Qt-7e662f3727e7c3dd3c41c29ed49bc41d2b66c744.tar.bz2
Fix construction races in QtNetwork
When two threads construct a QNetworkAccessManager at exactly the same time on an SMP system, there are construction races for some Q_GLOBAL_STATIC data. This is normal and expected - the losing thread deletes its instance as part of the Q_GLOBAL_STATIC macro. However, for two of the classes, destruction of the loser had side effects. For QNetworkConfigurationMangerPrivate, there was a crash because of uninitialised variable on the losing side. For QNetworkAccessBackendFactoryData, a guard mechanism intended to prevent the data being reconstructed by destructors of other global static classes was being set by the loser. To fix this, the bool is changed to a QAtomicInt. In the normal case, it will have value 0->1 on startup and 1->0 on shutdown. In the race case, it will have values 0->1->2->1 on startup and 1->0 on shutdown. Task-Number: QTBUG-20343 Reviewed-By: mread
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp15
1 files changed, 10 insertions, 5 deletions
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 2fae7d6..88c45d1 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -57,20 +57,25 @@
QT_BEGIN_NAMESPACE
-static bool factoryDataShutdown = false;
class QNetworkAccessBackendFactoryData: public QList<QNetworkAccessBackendFactory *>
{
public:
- QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive) { }
+ QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive)
+ {
+ valid.ref();
+ }
~QNetworkAccessBackendFactoryData()
{
QMutexLocker locker(&mutex); // why do we need to lock?
- factoryDataShutdown = true;
+ valid.deref();
}
QMutex mutex;
+ //this is used to avoid (re)constructing factory data from destructors of other global classes
+ static QAtomicInt valid;
};
Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
+QAtomicInt QNetworkAccessBackendFactoryData::valid;
QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
{
@@ -80,7 +85,7 @@ QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
{
- if (!factoryDataShutdown) {
+ if (QNetworkAccessBackendFactoryData::valid) {
QMutexLocker locker(&factoryData()->mutex);
factoryData()->removeAll(this);
}
@@ -89,7 +94,7 @@ QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
const QNetworkRequest &request)
{
- if (!factoryDataShutdown) {
+ if (QNetworkAccessBackendFactoryData::valid) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
end = factoryData()->constEnd();