From bb1504c271e18a26ad6ac20d55485c167671b1c2 Mon Sep 17 00:00:00 2001
From: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com>
Date: Thu, 5 Nov 2015 15:00:58 +0200
Subject: [PATCH] Fix QNetworkAccessManager crash at application shutdown
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Changed textures to use a common network access manager from
QML engine instead of each of them creating their own.

Change-Id: Ia70a756edc7f3c32679965a8edf28fa64be86dd4
Reviewed-by: Tomi Korpipää <tomi.korpipaa@theqtcompany.com>
Reviewed-by: Pasi Keränen <pasi.keranen@digia.com>
---
 src/imports/qtcanvas3d/teximage3d.cpp | 51 ++++++++++++++++-----------
 src/imports/qtcanvas3d/teximage3d_p.h |  7 ++--
 2 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/src/imports/qtcanvas3d/teximage3d.cpp b/src/imports/qtcanvas3d/teximage3d.cpp
index b6c0be2..38db6cf 100644
--- a/src/imports/qtcanvas3d/teximage3d.cpp
+++ b/src/imports/qtcanvas3d/teximage3d.cpp
@@ -154,7 +154,8 @@ QJSValue CanvasTextureImageFactory::newTexImage()
 CanvasTextureImage::CanvasTextureImage(CanvasTextureImageFactory *parent, QQmlEngine *engine) :
     CanvasAbstractObject(0, parent),
     m_engine(engine),
-    m_networkAccessManager(0),
+    m_networkAccessManager(m_engine->networkAccessManager()),
+    m_networkReply(0),
     m_state(INITIALIZED),
     m_errorString(""),
     m_pixelCache(0),
@@ -162,9 +163,6 @@ CanvasTextureImage::CanvasTextureImage(CanvasTextureImageFactory *parent, QQmlEn
     m_pixelCacheFlipY(false),
     m_parentFactory(parent)
 {
-    m_networkAccessManager = new QNetworkAccessManager(this);
-    QObject::connect(m_networkAccessManager, &QNetworkAccessManager::finished,
-                     this, &CanvasTextureImage::handleReply);
 }
 
 CanvasTextureImage::CanvasTextureImage(const QImage &source,
@@ -173,24 +171,32 @@ CanvasTextureImage::CanvasTextureImage(const QImage &source,
                                        QQmlEngine *engine) :
     CanvasAbstractObject(0, parent),
     m_engine(engine),
-    m_networkAccessManager(0),
+    m_networkAccessManager(m_engine->networkAccessManager()),
+    m_networkReply(0),
     m_state(INITIALIZED),
     m_errorString(""),
     m_pixelCache(0),
     m_pixelCacheFormat(CanvasContext::NONE),
     m_pixelCacheFlipY(false)
 {
-    m_networkAccessManager = new QNetworkAccessManager(this);
-    QObject::connect(m_networkAccessManager, &QNetworkAccessManager::finished,
-                     this, &CanvasTextureImage::handleReply);
-
     m_image = source.scaled(width, height);
     setImageState(LOADING_FINISHED);
 }
 
+void CanvasTextureImage::cleanupNetworkReply()
+{
+    if (m_networkReply) {
+        QObject::disconnect(m_networkReply, &QNetworkReply::finished,
+                            this, &CanvasTextureImage::handleReply);
+        m_networkReply->abort();
+        m_networkReply->deleteLater();
+        m_networkReply = 0;
+    }
+}
+
 CanvasTextureImage::~CanvasTextureImage()
 {
-    delete m_networkAccessManager;
+    cleanupNetworkReply();
     delete m_pixelCache;
 }
 
@@ -250,7 +256,9 @@ void CanvasTextureImage::load()
     emit imageLoadingStarted(this);
 
     QNetworkRequest request(m_source);
-    m_networkAccessManager->get(request);
+    m_networkReply = m_networkAccessManager->get(request);
+    QObject::connect(m_networkReply, &QNetworkReply::finished,
+                     this, &CanvasTextureImage::handleReply);
 }
 
 /*!
@@ -262,18 +270,19 @@ QString CanvasTextureImage::errorString() const
     return m_errorString;
 }
 
-void CanvasTextureImage::handleReply(QNetworkReply *reply)
+void CanvasTextureImage::handleReply()
 {
-    if (reply->error() != QNetworkReply::NoError) {
-        m_errorString = reply->errorString();
-        emit errorStringChanged(m_errorString);
-        setImageState(LOADING_ERROR);
-        return;
+    if (m_networkReply) {
+        if (m_networkReply->error() != QNetworkReply::NoError) {
+            m_errorString = m_networkReply->errorString();
+            emit errorStringChanged(m_errorString);
+            setImageState(LOADING_ERROR);
+        } else {
+            m_image.loadFromData(m_networkReply->readAll());
+            setImageState(LOADING_FINISHED);
+        }
+        cleanupNetworkReply();
     }
-
-    m_image.loadFromData(reply->readAll());
-
-    setImageState(LOADING_FINISHED);
 }
 
 QImage &CanvasTextureImage::getImage()
diff --git a/src/imports/qtcanvas3d/teximage3d_p.h b/src/imports/qtcanvas3d/teximage3d_p.h
index 70b7f1c..78a6679 100644
--- a/src/imports/qtcanvas3d/teximage3d_p.h
+++ b/src/imports/qtcanvas3d/teximage3d_p.h
@@ -120,7 +120,7 @@ public:
     void emitImageLoadingError();
 
     void load();
-    void handleReply(QNetworkReply *reply);
+    void handleReply();
     QImage &getImage();
     uchar *convertToFormat(CanvasContext::glEnums format, bool flipY = false, bool premultipliedAlpha = false);
 
@@ -143,8 +143,11 @@ signals:
     void imageLoadingFailed(CanvasTextureImage *image);
 
 private:
+    void cleanupNetworkReply();
+
     QQmlEngine *m_engine;
-    QNetworkAccessManager *m_networkAccessManager;
+    QNetworkAccessManager *m_networkAccessManager; // not owned
+    QNetworkReply *m_networkReply;
     QImage m_image;
     QUrl m_source;
     TextureImageState m_state;
-- 
GitLab