Safer ContentManager::reallyCancelBook()

Before this change `ContentManager::reallyCancelBook()` could throw (and
thus result in a crash) if the confirmation to cancel the download was
timed to perform the actual download cancellation on a completed
download. This change fixes that problem. Besides it also fixes a subtle
issue where `ContentManager::reallyCancelBook()` is called on a
completed download and has the effect of removing the downloaded book
from the local library. I considered preserving that dubious behaviour,
but it couldn't be achieved in a simple and consistent fashion (because
of the two ways an actually completed download can be seen by the
`ContentManager::reallyCancelBook()` function).
This commit is contained in:
Veloman Yunkan 2024-03-10 18:45:03 +04:00
parent fa418a6aa0
commit b141677810

View File

@ -722,10 +722,24 @@ void ContentManager::cancelBook(const QString& id)
void ContentManager::reallyCancelBook(const QString& id)
{
auto& b = mp_library->getBookById(id);
auto download = mp_downloader->getDownload(b.getDownloadId());
if (download->getStatus() != kiwix::Download::K_COMPLETE) {
const auto downloadId = mp_library->getBookById(id).getDownloadId();
if ( downloadId.empty() ) {
// Completion of the download has been detected (and its id was reset)
// before the confirmation to cancel the download was granted.
return;
}
auto download = mp_downloader->getDownload(downloadId);
try {
download->cancelDownload();
} catch (const kiwix::AriaError&) {
// Download has completed before the cancel request was handled.
// Most likely the download was already complete at the time
// when ContentManager::reallyCancelBook() started executing, but
// its completion was not yet detected (and/or handled) by the
// download updater thread (letting the code pass past the empty
// downloadId check above).
return;
}
removeDownload(id);