From 3698da02772230d068e1f068d3997b6b88f8f27e 2017-07-17 15:19:57 From: mperrinel Date: 2017-07-17 15:19:57 Subject: [PATCH] Add thread protection on AbortDownload process --- diff --git a/core/src/Network/NetworkController.cpp b/core/src/Network/NetworkController.cpp index 64c0bb8..64f3d82 100644 --- a/core/src/Network/NetworkController.cpp +++ b/core/src/Network/NetworkController.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -14,8 +15,13 @@ struct NetworkController::NetworkControllerPrivate { explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {} QMutex m_WorkingMutex; + QReadWriteLock m_Lock; std::unordered_map m_NetworkReplyToVariableId; std::unique_ptr m_AccessManager{nullptr}; + + void lockRead() { m_Lock.lockForRead(); } + void lockWrite() { m_Lock.lockForWrite(); } + void unlock() { m_Lock.unlock(); } }; NetworkController::NetworkController(QObject *parent) @@ -26,30 +32,50 @@ NetworkController::NetworkController(QObject *parent) void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier, std::function callback) { - qCInfo(LOG_NetworkController()) << tr("NetworkController registered") - << QThread::currentThread(); auto reply = impl->m_AccessManager->get(request); + qCDebug(LOG_NetworkController()) << tr("NetworkController registered") + << QThread::currentThread() << reply; // Store the couple reply id + impl->lockWrite(); impl->m_NetworkReplyToVariableId[reply] = identifier; + impl->unlock(); auto onReplyFinished = [reply, this, identifier, callback]() { - qCInfo(LOG_NetworkController()) << tr("NetworkController onReplyFinished") - << QThread::currentThread(); + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished") + << QThread::currentThread() << reply; + impl->lockRead(); auto it = impl->m_NetworkReplyToVariableId.find(reply); + impl->unlock(); if (it != impl->m_NetworkReplyToVariableId.cend()) { + impl->lockWrite(); + impl->m_NetworkReplyToVariableId.erase(reply); + impl->unlock(); + // Deletes reply callback(reply, identifier); + reply->deleteLater(); + + emit this->replyDownloadProgress(identifier, 0); } + + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END") + << QThread::currentThread() << reply; }; auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) { double progress = (bytesRead * 100.0) / totalBytes; + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress + << QThread::currentThread() << reply; + impl->lockRead(); auto it = impl->m_NetworkReplyToVariableId.find(reply); + impl->unlock(); if (it != impl->m_NetworkReplyToVariableId.cend()) { emit this->replyDownloadProgress(it->second, progress); } + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END") + << QThread::currentThread() << reply; }; @@ -73,12 +99,19 @@ void NetworkController::finalize() void NetworkController::onReplyCanceled(QUuid identifier) { auto findReply = [identifier](const auto &entry) { return identifier == entry.second; }; + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled") + << QThread::currentThread(); + + impl->lockRead(); auto end = impl->m_NetworkReplyToVariableId.cend(); auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply); + impl->unlock(); if (it != end) { it->first->abort(); } + qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END") + << QThread::currentThread(); } void NetworkController::waitForFinish() diff --git a/core/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index 43c703e..0f96d50 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -178,8 +178,8 @@ void VariableController::onAbortProgressRequested(std::shared_ptr vari qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested" << QThread::currentThread()->objectName(); - auto it = impl->m_VariableToIdentifier.find(variable); - if (it != impl->m_VariableToIdentifier.cend()) { + auto it = impl->m_VariableToIdentifierMap.find(variable); + if (it != impl->m_VariableToIdentifierMap.cend()) { impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second); } else {