forked from premiere/premiere-libtorrent
Fix storage initialization (#2944)
If `default_storage::has_any_file` fails during fastresume data check, `piece_manager::check_no_fastresume` will skip storage initialization. In such case, any storage operation that require part file will cause an application crash.
This commit is contained in:
parent
e1f99fb309
commit
44479bcca3
|
@ -352,10 +352,14 @@ TORRENT_EXPORT void assert_fail(char const* expr, int line
|
||||||
|
|
||||||
// if production asserts are defined, don't abort, just print the error
|
// if production asserts are defined, don't abort, just print the error
|
||||||
#ifndef TORRENT_PRODUCTION_ASSERTS
|
#ifndef TORRENT_PRODUCTION_ASSERTS
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__debugbreak();
|
||||||
|
#else
|
||||||
// send SIGINT to the current process
|
// send SIGINT to the current process
|
||||||
// to break into the debugger
|
// to break into the debugger
|
||||||
raise(SIGABRT);
|
raise(SIGABRT);
|
||||||
abort();
|
abort();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1792,19 +1792,10 @@ namespace libtorrent
|
||||||
|
|
||||||
int piece_manager::check_no_fastresume(storage_error& ec)
|
int piece_manager::check_no_fastresume(storage_error& ec)
|
||||||
{
|
{
|
||||||
bool has_files = false;
|
|
||||||
if (!m_storage->settings().get_bool(settings_pack::no_recheck_incomplete_resume))
|
if (!m_storage->settings().get_bool(settings_pack::no_recheck_incomplete_resume))
|
||||||
{
|
{
|
||||||
storage_error se;
|
storage_error se;
|
||||||
has_files = m_storage->has_any_file(se);
|
if (m_storage->has_any_file(se))
|
||||||
|
|
||||||
if (se)
|
|
||||||
{
|
|
||||||
ec = se;
|
|
||||||
return fatal_disk_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_files)
|
|
||||||
{
|
{
|
||||||
// always initialize the storage
|
// always initialize the storage
|
||||||
int ret = check_init_storage(ec);
|
int ret = check_init_storage(ec);
|
||||||
|
|
|
@ -415,6 +415,18 @@ void test_rename(std::string const& test_path)
|
||||||
TEST_EQUAL(s->files().file_path(0), "new_filename");
|
TEST_EQUAL(s->files().file_path(0), "new_filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct test_error_storage : default_storage
|
||||||
|
{
|
||||||
|
test_error_storage(storage_params const& params) : default_storage(params) {};
|
||||||
|
|
||||||
|
bool has_any_file(storage_error& ec) TORRENT_FINAL
|
||||||
|
{
|
||||||
|
ec.ec = make_error_code(boost::system::errc::permission_denied);
|
||||||
|
ec.operation = storage_error::stat;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void test_check_files(std::string const& test_path
|
void test_check_files(std::string const& test_path
|
||||||
, libtorrent::storage_mode_t storage_mode
|
, libtorrent::storage_mode_t storage_mode
|
||||||
, bool unbuffered)
|
, bool unbuffered)
|
||||||
|
@ -458,22 +470,21 @@ void test_check_files(std::string const& test_path
|
||||||
bencode(std::back_inserter(buf), t.generate());
|
bencode(std::back_inserter(buf), t.generate());
|
||||||
info = boost::make_shared<torrent_info>(&buf[0], buf.size(), boost::ref(ec), 0);
|
info = boost::make_shared<torrent_info>(&buf[0], buf.size(), boost::ref(ec), 0);
|
||||||
|
|
||||||
aux::session_settings set;
|
|
||||||
file_pool fp;
|
file_pool fp;
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_service ios;
|
||||||
counters cnt;
|
counters cnt;
|
||||||
disk_io_thread io(ios, cnt, NULL);
|
disk_io_thread io(ios, cnt, NULL);
|
||||||
io.set_num_threads(1);
|
io.set_num_threads(1);
|
||||||
disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop));
|
std::vector<uint8_t> prio(info->num_files(), 0);
|
||||||
storage_params p;
|
storage_params p;
|
||||||
p.files = &fs;
|
p.files = &fs;
|
||||||
p.path = test_path;
|
p.path = test_path;
|
||||||
p.pool = &fp;
|
p.pool = &fp;
|
||||||
p.mode = storage_mode;
|
p.mode = storage_mode;
|
||||||
|
p.priorities = &prio;
|
||||||
|
|
||||||
boost::shared_ptr<void> dummy;
|
boost::shared_ptr<void> dummy;
|
||||||
boost::shared_ptr<piece_manager> pm = boost::make_shared<piece_manager>(new default_storage(p), dummy, &fs);
|
boost::shared_ptr<piece_manager> pm = boost::make_shared<piece_manager>(new test_error_storage(p), dummy, &fs);
|
||||||
libtorrent::mutex lock;
|
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
bdecode_node frd;
|
bdecode_node frd;
|
||||||
|
@ -481,10 +492,18 @@ void test_check_files(std::string const& test_path
|
||||||
io.async_check_fastresume(pm.get(), &frd, links
|
io.async_check_fastresume(pm.get(), &frd, links
|
||||||
, boost::bind(&on_check_resume_data, _1, &done));
|
, boost::bind(&on_check_resume_data, _1, &done));
|
||||||
io.submit_jobs();
|
io.submit_jobs();
|
||||||
ios.reset();
|
|
||||||
run_until(ios, done);
|
run_until(ios, done);
|
||||||
|
|
||||||
io.set_num_threads(0);
|
for (int i = 0; i < info->num_pieces(); ++i)
|
||||||
|
{
|
||||||
|
done = false;
|
||||||
|
io.async_hash(pm.get(), i, disk_io_job::sequential_access | disk_io_job::volatile_read
|
||||||
|
, boost::bind(&on_check_resume_data, _1, &done), reinterpret_cast<void*>(1));
|
||||||
|
io.submit_jobs();
|
||||||
|
run_until(ios, done);
|
||||||
|
}
|
||||||
|
|
||||||
|
io.abort(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 2 split this test up into smaller parts
|
// TODO: 2 split this test up into smaller parts
|
||||||
|
|
Loading…
Reference in New Issue