avoid concurrent access to hash offset
Since partial_hash::offset is not an atomic it is technically UD to access it concurrently from multiple threads.
This commit is contained in:
parent
241e9fd25a
commit
f36b9a805a
|
@ -2153,6 +2153,9 @@ namespace libtorrent
|
|||
DLOG("kick_hasher: %d - %d (piece: %d offset: %d)\n"
|
||||
, cursor, end, int(pe->piece), ph->offset);
|
||||
|
||||
// save a local copy of offset to avoid concurrent access
|
||||
int offset = ph->offset;
|
||||
|
||||
l.unlock();
|
||||
|
||||
time_point start_time = clock_type::now();
|
||||
|
@ -2160,15 +2163,17 @@ namespace libtorrent
|
|||
for (int i = cursor; i < end; ++i)
|
||||
{
|
||||
cached_block_entry& bl = pe->blocks[i];
|
||||
int size = (std::min)(block_size, piece_size - ph->offset);
|
||||
int size = (std::min)(block_size, piece_size - offset);
|
||||
ph->h.update(bl.buf, size);
|
||||
ph->offset += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
boost::uint64_t hash_time = total_microseconds(clock_type::now() - start_time);
|
||||
|
||||
l.lock();
|
||||
|
||||
ph->offset = offset;
|
||||
|
||||
TORRENT_PIECE_ASSERT(pe->hashing, pe);
|
||||
TORRENT_PIECE_ASSERT(pe->hash, pe);
|
||||
|
||||
|
@ -2388,22 +2393,25 @@ namespace libtorrent
|
|||
// to keep the cache footprint low, try to evict a volatile piece
|
||||
m_disk_cache.try_evict_one_volatile();
|
||||
|
||||
// save a local copy of offset to avoid concurrent access
|
||||
int offset = ph->offset;
|
||||
|
||||
l.unlock();
|
||||
|
||||
int ret = 0;
|
||||
int next_locked_block = 0;
|
||||
for (int i = ph->offset / block_size; i < blocks_in_piece; ++i)
|
||||
for (int i = offset / block_size; i < blocks_in_piece; ++i)
|
||||
{
|
||||
file::iovec_t iov;
|
||||
iov.iov_len = (std::min)(block_size, piece_size - ph->offset);
|
||||
iov.iov_len = (std::min)(block_size, piece_size - offset);
|
||||
|
||||
if (next_locked_block < num_locked_blocks
|
||||
&& locked_blocks[next_locked_block] == i)
|
||||
{
|
||||
++next_locked_block;
|
||||
TORRENT_PIECE_ASSERT(pe->blocks[i].buf, pe);
|
||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
||||
ph->offset += iov.iov_len;
|
||||
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||
offset += iov.iov_len;
|
||||
ph->h.update(pe->blocks[i].buf, iov.iov_len);
|
||||
}
|
||||
else
|
||||
|
@ -2436,9 +2444,9 @@ namespace libtorrent
|
|||
|
||||
time_point start_time = clock_type::now();
|
||||
|
||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
||||
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||
ret = j->storage->get_storage_impl()->readv(&iov, 1, j->piece
|
||||
, ph->offset, file_flags, j->error);
|
||||
, offset, file_flags, j->error);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
|
@ -2474,8 +2482,8 @@ namespace libtorrent
|
|||
m_stats_counters.inc_stats_counter(counters::disk_job_time, read_time);
|
||||
}
|
||||
|
||||
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
|
||||
ph->offset += iov.iov_len;
|
||||
TORRENT_PIECE_ASSERT(offset == i * block_size, pe);
|
||||
offset += iov.iov_len;
|
||||
ph->h.update(static_cast<char const*>(iov.iov_base), iov.iov_len);
|
||||
|
||||
l.lock();
|
||||
|
@ -2486,6 +2494,8 @@ namespace libtorrent
|
|||
|
||||
l.lock();
|
||||
|
||||
ph->offset = offset;
|
||||
|
||||
// decrement the refcounts of the blocks we just hashed
|
||||
for (int i = 0; i < num_locked_blocks; ++i)
|
||||
m_disk_cache.dec_block_refcount(pe, locked_blocks[i], block_cache::ref_hashing);
|
||||
|
|
Loading…
Reference in New Issue