From 517afdfff3dafddc7ebe6b050c2c8ae7a1b4fb8b Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 12 Jul 2019 01:47:59 -0400 Subject: [PATCH] make sure timers don't fire after restart MO fixes crash when request times out after the restart --- src/github.cpp | 44 +++++++++++++++++++++++++++++++++++++++----- src/github.h | 6 ++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/github.cpp b/src/github.cpp index 4215c66..4c67aec 100644 --- a/src/github.cpp +++ b/src/github.cpp @@ -21,6 +21,16 @@ GitHub::GitHub(const char *clientId) } } +GitHub::~GitHub() +{ + // delete all the replies since they depend on the access manager, which is + // about to be deleted + for (auto* reply : m_replies) { + reply->disconnect(); + delete reply; + } +} + QJsonArray GitHub::releases(const Repository &repo) { QJsonDocument result @@ -114,11 +124,18 @@ void GitHub::request(Method method, const QString &path, const QByteArray &data, const std::function &callback, bool relative) { - QTimer *timer = new QTimer(); + // make sure the timer is a child of this so it's deleted correctly and + // doesn't fire after the GitHub object is destroyed; this happens when + // restarting MO by switching instances, for example + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); timer->setInterval(30000); QNetworkReply *reply = genReply(method, path, data, relative); + // remember this reply + m_replies.push_back(reply); + connect(reply, &QNetworkReply::finished, [this, reply, timer, method, data, callback]() { QJsonDocument result = handleReply(reply); QJsonObject object = result.object(); @@ -129,24 +146,41 @@ void GitHub::request(Method method, const QString &path, const QByteArray &data, } else { callback(result); } - reply->deleteLater(); + + deleteReply(reply); }); connect(reply, static_cast( &QNetworkReply::error), - [reply, timer, callback](QNetworkReply::NetworkError error) { + [this, reply, timer, callback](QNetworkReply::NetworkError error) { qDebug("network error %d", error); timer->stop(); reply->disconnect(); callback(QJsonDocument( QJsonObject({{"network_error", reply->errorString()}}))); - reply->deleteLater(); + + deleteReply(reply); }); - connect(timer, &QTimer::timeout, [reply]() { + connect(timer, &QTimer::timeout, [this, reply]() { qDebug("timeout"); + + // don't delete the reply, abort will fire the error() handler above reply->abort(); }); + timer->start(); } + +void GitHub::deleteReply(QNetworkReply* reply) +{ + // remove from the list + auto itor = std::find(m_replies.begin(), m_replies.end(), reply); + if (itor != m_replies.end()) { + m_replies.erase(itor); + } + + // delete + reply->deleteLater(); +} diff --git a/src/github.h b/src/github.h index 3f26724..9faaca2 100644 --- a/src/github.h +++ b/src/github.h @@ -67,6 +67,7 @@ public: public: GitHub(const char *clientId = nullptr); + ~GitHub(); QJsonArray releases(const Repository &repo); void releases(const Repository &repo, @@ -85,4 +86,9 @@ private: private: QNetworkAccessManager *m_AccessManager; + + // remember the replies that are in flight and delete them in the destructor + std::vector m_replies; + + void deleteReply(QNetworkReply* reply); };