diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 9a8fb884d..4a536d12b 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -651,7 +651,7 @@ namespace libtorrent enum return_t { - // return values from check_fastresume + // return values from check_fastresume, and move_storage no_error = 0, fatal_disk_error = -1, need_full_check = -2, diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 103e03983..dfca3affc 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -2375,7 +2375,8 @@ namespace libtorrent pe->hashing = 1; - TORRENT_PIECE_ASSERT(pe->cache_state <= cached_piece_entry::read_lru1 || pe->cache_state == cached_piece_entry::read_lru2, pe); + TORRENT_PIECE_ASSERT(pe->cache_state <= cached_piece_entry::read_lru1 + || pe->cache_state == cached_piece_entry::read_lru2, pe); ++pe->piece_refcount; if (pe->hash == NULL) @@ -2472,6 +2473,19 @@ namespace libtorrent break; } + // 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 (ret != iov.iov_len) + { + ret = -1; + j->error.ec.assign(boost::asio::error::eof + , boost::asio::error::get_misc_category()); + m_disk_cache.free_buffer((char*)iov.iov_base); + l.lock(); + break; + } + if (!j->error.ec) { boost::uint32_t read_time = total_microseconds(time_now_hires() - start_time); diff --git a/src/file.cpp b/src/file.cpp index 3200878ce..ad573570a 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1583,7 +1583,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { if (tmp_ret < 0) { #ifdef TORRENT_WINDOWS - ec.assign(last_error, system_category()); + ec.assign(GetLastError(), system_category()); #else ec.assign(errno, get_posix_category()); #endif @@ -1596,7 +1596,7 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { return ret; -#else +#else // not PREADV nor PREAD int ret = 0; diff --git a/src/torrent.cpp b/src/torrent.cpp index cb2b3dd42..4ac3ad04f 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2421,7 +2421,7 @@ namespace libtorrent dec_refcount("force_recheck"); state_updated(); - if (j->ret == piece_manager::fatal_disk_error) + if (j->ret < 0) { handle_disk_error(j); return; @@ -2514,9 +2514,10 @@ namespace libtorrent ++m_num_checked_pieces; - if (j->ret == piece_manager::fatal_disk_error) + if (j->ret < 0) { - if (j->error.ec == boost::system::errc::no_such_file_or_directory) + if (j->error.ec == boost::system::errc::no_such_file_or_directory + || j->error.ec == boost::asio::error::eof) { // skip this file by updating m_checking_piece to the first piece following it file_storage const& st = m_torrent_file->files();