Always disconnect signals on aborted reply objects
authorBea Lam <bea.lam@nokia.com>
Mon, 22 Aug 2011 04:44:26 +0000 (14:44 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 22 Aug 2011 07:05:29 +0000 (09:05 +0200)
reload() did not disconnect the model from an aborted reply's
signals, and if it received a finished() signal from the aborted
reply it crashed when trying to access the deleted d->reply.

Task-number: QTBUG-20842

(cherry-picked from commit d3599ab224f00915045562562c7fd4d6b9b9aeb4
in 4.8)

Change-Id: I09a4b04ccdcf04d0ad19052475376e4d1910b7b9
Reviewed-on: http://codereview.qt.nokia.com/3282
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Bea Lam <bea.lam@nokia.com>
src/declarative/util/qdeclarativexmllistmodel.cpp

index 86e6e9e..47ef762 100644 (file)
@@ -537,6 +537,15 @@ public:
         emit q->statusChanged(status);
     }
 
+    void deleteReply() {
+        Q_Q(QDeclarativeXmlListModel);
+        if (reply) {
+            QObject::disconnect(reply, 0, q, 0);
+            reply->deleteLater();
+            reply = 0;
+        }
+    }
+
     bool isComponentComplete;
     QUrl src;
     QString xml;
@@ -546,6 +555,7 @@ public:
     QList<int> roles;
     QStringList roleNames;
     int highestRole;
+
     QNetworkReply *reply;
     QDeclarativeXmlListModel::Status status;
     QString errorString;
@@ -553,6 +563,7 @@ public:
     int queryId;
     QStringList keyRoleResultsCache;
     QList<QDeclarativeXmlListModelRole *> roleObjects;
+
     static void append_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list, QDeclarativeXmlListModelRole *role);
     static void clear_role(QDeclarativeListProperty<QDeclarativeXmlListModelRole> *list);
     QList<QList<QVariant> > data;
@@ -998,11 +1009,7 @@ void QDeclarativeXmlListModel::reload()
 
     if (d->reply) {
         d->reply->abort();
-        if (d->reply) {
-            // abort will generally have already done this (and more)
-            d->reply->deleteLater();
-            d->reply = 0;
-        }
+        d->deleteReply();
     }
 
     if (!d->xml.isEmpty()) {
@@ -1036,8 +1043,7 @@ void QDeclarativeXmlListModel::requestFinished()
         QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
         if (redirect.isValid()) {
             QUrl url = d->reply->url().resolved(redirect.toUrl());
-            d->reply->deleteLater();
-            d->reply = 0;
+            d->deleteReply();
             setSource(url);
             return;
         }
@@ -1046,9 +1052,7 @@ void QDeclarativeXmlListModel::requestFinished()
 
     if (d->reply->error() != QNetworkReply::NoError) {
         d->errorString = d->reply->errorString();
-        disconnect(d->reply, 0, this, 0);
-        d->reply->deleteLater();
-        d->reply = 0;
+        d->deleteReply();
 
         int count = this->count();
         d->data.clear();
@@ -1069,9 +1073,7 @@ void QDeclarativeXmlListModel::requestFinished()
         } else {
             d->queryId = QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
         }
-        disconnect(d->reply, 0, this, 0);
-        d->reply->deleteLater();
-        d->reply = 0;
+        d->deleteReply();
 
         d->progress = 1.0;
         emit progressChanged(d->progress);