arvidn / libtorrent

an efficient feature complete C++ bittorrent implementation

Home Page:http://libtorrent.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unrecoverable file error after reboot during download

alervd opened this issue · comments

commented

libtorrent version (or branch): 1.2.18.
platform/architecture: Windows 10/11 x86_64.
compiler and compiler version: Microsoft Visual C++ 2019.

Hello,

Steps to reproduce:

  1. Start downloading a torrent.
  2. Reboot computer (don't stop torrent before reboot).
  3. Try to start (resume) downloading of that torrent. Result: Libtorrent generates status_t::fatal_disk_error (boost::asio::error::eof) and won't resume the downloading.

The code which generates the error:

// treat a short read as an error. The hash will be invalid, the
// block cannot be cached and the main thread should skip the rest
// of this file
if (read_ret != int(iov.size()))
{
    ret = status_t::fatal_disk_error;
    j->error.ec = boost::asio::error::eof;
    j->error.operation = operation_t::file_read;
    break;
}

It's located inside of disk_io_thread::do_hash method.

So, as far as I understand, Libtorrent thinks (according to resume data) that it has a piece it has downloaded recently and tries to check its hash. But it can't because OS did not manage to flash the data to disk, so it just does not exist on the disk.

What I suggest: Libtorrent should just drop such pieces (maybe issue a warning) and re-download them again. Otherwise the user is stuck with damaged torrent download he can't resume.

I'm able to 100% reproduce this issue using VirtualBox's virtual machine and external USB NTFS drive connected to it. I was NOT able to reproduce this issue on a real machine. However, one of our users reported that he experience this issue on a real PC with exFAT external drive. I've tried exFAT too - no luck.

I believe this behavior is by design. silently ignoring disk errors is risky. The way you resume from a disk error (or any error to a torrent) is to call torrent_handle::clear_error()

although, I agree that during the checking of files on disk it makes sense to be very tolerant of files being shorter than expected, for instance.

commented

I believe this behavior is by design. silently ignoring disk errors is risky. The way you resume from a disk error (or any error to a torrent) is to call torrent_handle::clear_error()

Wow didn't know about it. I'll check it, thanks! :)

commented

although, I agree that during the checking of files on disk it makes sense to be very tolerant of files being shorter than expected, for instance.

Yes, that would be nice.

commented

The way you resume from a disk error (or any error to a torrent) is to call torrent_handle::clear_error()

This does not help. Can't resume such a torrent using clear_error().

commented

I think that the only way to resume such a torrent for now is to drop broken fast resume data so LT will re-check existing files. Not a very good solution, but it seems it's the only one.