diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 6a1fd4a49..9d85c7944 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -1030,11 +1030,12 @@ void SessionImpl::setGlobalMaxSeedingMinutes(int minutes) // Main destructor SessionImpl::~SessionImpl() { - saveStatistics(); - - // Do some BT related saving + // Do some bittorrent related saving + // After this, (ideally) no more important alerts will be generated/handled saveResumeData(); + saveStatistics(); + // We must delete FilterParserThread // before we delete lt::session delete m_filterParser; @@ -2444,6 +2445,12 @@ void SessionImpl::handleTorrentSaveResumeDataRequested(const TorrentImpl *torren ++m_numResumeData; } +void SessionImpl::handleTorrentSaveResumeDataFailed(const TorrentImpl *torrent) +{ + Q_UNUSED(torrent); + --m_numResumeData; +} + QVector SessionImpl::torrents() const { QVector result; @@ -2892,28 +2899,37 @@ void SessionImpl::saveResumeData() ++m_numResumeData; } + QElapsedTimer timer; + timer.start(); + while (m_numResumeData > 0) { - const std::vector alerts = getPendingAlerts(lt::seconds {30}); - if (alerts.empty()) - { - LogMsg(tr("Aborted saving resume data. Number of outstanding torrents: %1").arg(QString::number(m_numResumeData)) - , Log::CRITICAL); - break; - } + const lt::seconds waitTime {5}; + const lt::seconds expireTime {30}; + const std::vector alerts = getPendingAlerts(waitTime); + bool hasWantedAlert = false; for (const lt::alert *a : alerts) { - switch (a->type()) + if (const int alertType = a->type(); + (alertType == lt::save_resume_data_alert::alert_type) + || (alertType == lt::save_resume_data_failed_alert::alert_type)) { - case lt::save_resume_data_failed_alert::alert_type: - --m_numResumeData; - break; - case lt::save_resume_data_alert::alert_type: - dispatchTorrentAlert(static_cast(a)); - break; + hasWantedAlert = true; + handleAlert(a); } } + + if (hasWantedAlert) + { + timer.start(); + } + else if (timer.hasExpired(lt::total_milliseconds(expireTime))) + { + LogMsg(tr("Aborted saving resume data. Number of outstanding torrents: %1").arg(QString::number(m_numResumeData)) + , Log::CRITICAL); + break; + } } } diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 0d105a395..c09ef72fe 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -410,6 +410,7 @@ namespace BitTorrent // Torrent interface void handleTorrentNeedSaveResumeData(const TorrentImpl *torrent); void handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent); + void handleTorrentSaveResumeDataFailed(const TorrentImpl *torrent); void handleTorrentShareLimitChanged(TorrentImpl *const torrent); void handleTorrentNameChanged(TorrentImpl *const torrent); void handleTorrentSavePathChanged(TorrentImpl *const torrent); diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index 94d65587b..d79c45df6 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -1949,8 +1949,13 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms) void TorrentImpl::handleSaveResumeDataFailedAlert(const lt::save_resume_data_failed_alert *p) { - Q_UNUSED(p); - Q_ASSERT_X(false, Q_FUNC_INFO, "This point should be unreachable since libtorrent 1.2.11"); + if (p->error != lt::errors::resume_data_not_modified) + { + LogMsg(tr("Generate resume data failed. Torrent: \"%1\". Reason: \"%2\"") + .arg(name(), QString::fromLocal8Bit(p->error.message().c_str())), Log::CRITICAL); + } + + m_session->handleTorrentSaveResumeDataFailed(this); } void TorrentImpl::handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p)