summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarkus Goetz <Markus.Goetz@nokia.com>2009-06-24 13:59:49 (GMT)
committerMarkus Goetz <Markus.Goetz@nokia.com>2009-06-25 11:00:22 (GMT)
commite5b8db6d4ecc244f7c35ea96a1f4e76fad47f1c4 (patch)
tree9eb36d2a2e5852db5758f4e9ebbe0b7787406e32 /src
parent4b9784fcdd7321a5d82b8ae73edd1ae52786d7ad (diff)
downloadQt-e5b8db6d4ecc244f7c35ea96a1f4e76fad47f1c4.zip
Qt-e5b8db6d4ecc244f7c35ea96a1f4e76fad47f1c4.tar.gz
Qt-e5b8db6d4ecc244f7c35ea96a1f4e76fad47f1c4.tar.bz2
QNetworkReplyImpl: Protect against recursive event loops
This fixes a bug that occured together with a QProgressDialog. The signal emission was like: readyRead readyRead readyRead [...] readyRead finished readyRead Now finished should be properly at the ending of this sequence. Task-number: 256630 Reviewed-by: Thiago Macieira <thiago.macieira@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp36
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h5
2 files changed, 39 insertions, 2 deletions
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index e8cb6ee..d903d03 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
: copyDevice(0), networkCache(0),
cacheEnabled(false), cacheSaveDevice(0),
+ notificationHandlingPaused(false),
bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1),
state(Idle)
{
@@ -164,9 +165,11 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
lastBytesDownloaded = bytesDownloaded;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ pauseNotificationHandling();
emit q->downloadProgress(bytesDownloaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
emit q->readyRead();
+ resumeNotificationHandling();
}
void QNetworkReplyImplPrivate::_q_copyReadChannelFinished()
@@ -210,6 +213,9 @@ void QNetworkReplyImplPrivate::backendNotify(InternalNotifications notification)
void QNetworkReplyImplPrivate::handleNotifications()
{
+ if (notificationHandlingPaused)
+ return;
+
NotificationQueue current = pendingNotifications;
pendingNotifications.clear();
@@ -248,6 +254,22 @@ void QNetworkReplyImplPrivate::handleNotifications()
}
}
+// Do not handle the notifications while we are emitting downloadProgress
+// or readyRead
+void QNetworkReplyImplPrivate::pauseNotificationHandling()
+{
+ notificationHandlingPaused = true;
+}
+
+// Resume notification handling
+void QNetworkReplyImplPrivate::resumeNotificationHandling()
+{
+ Q_Q(QNetworkReplyImpl);
+ notificationHandlingPaused = false;
+ if (pendingNotifications.size() >= 1)
+ QCoreApplication::postEvent(q, new QEvent(QEvent::NetworkReplyUpdated));
+}
+
void QNetworkReplyImplPrivate::createCache()
{
// check if we can save and if we're allowed to
@@ -318,8 +340,10 @@ void QNetworkReplyImplPrivate::consume(qint64 count)
bytesUploaded += count;
QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader);
+ pauseNotificationHandling();
emit q->uploadProgress(bytesUploaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+ resumeNotificationHandling();
}
qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
@@ -367,12 +391,14 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data)
QPointer<QNetworkReplyImpl> qq = q;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ pauseNotificationHandling();
emit q->downloadProgress(bytesDownloaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
emit q->readyRead();
// hopefully we haven't been deleted here
if (!qq.isNull()) {
+ resumeNotificationHandling();
// do we still have room in the buffer?
if (nextDownstreamBlockSize() > 0)
backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
@@ -409,19 +435,25 @@ void QNetworkReplyImplPrivate::finished()
state = Finished;
pendingNotifications.clear();
+ pauseNotificationHandling();
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
- if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull())
+ if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull()) {
emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
- if (bytesUploaded == -1 && outgoingData)
+ }
+ if (bytesUploaded == -1 && outgoingData) {
emit q->uploadProgress(0, 0);
+ }
+ resumeNotificationHandling();
completeCacheSave();
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
+ pauseNotificationHandling();
emit q->readChannelFinished();
emit q->finished();
+ resumeNotificationHandling();
}
void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const QString &errorMessage)
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 32bfa4c..65b3679 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -129,6 +129,9 @@ public:
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
void setNetworkCache(QAbstractNetworkCache *networkCache);
+
+ void pauseNotificationHandling();
+ void resumeNotificationHandling();
void backendNotify(InternalNotifications notification);
void handleNotifications();
void createCache();
@@ -156,6 +159,8 @@ public:
QIODevice *cacheSaveDevice;
NotificationQueue pendingNotifications;
+ bool notificationHandlingPaused;
+
QUrl urlForLastAuthentication;
#ifndef QT_NO_NETWORKPROXY
QNetworkProxy lastProxyAuthentication;