diff options
author | Markus Goetz <Markus.Goetz@nokia.com> | 2009-06-24 13:59:49 (GMT) |
---|---|---|
committer | Markus Goetz <Markus.Goetz@nokia.com> | 2009-06-25 11:00:22 (GMT) |
commit | e5b8db6d4ecc244f7c35ea96a1f4e76fad47f1c4 (patch) | |
tree | 9eb36d2a2e5852db5758f4e9ebbe0b7787406e32 /src/network/access | |
parent | 4b9784fcdd7321a5d82b8ae73edd1ae52786d7ad (diff) | |
download | Qt-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/network/access')
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 36 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl_p.h | 5 |
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; |