wallet: protect against exceptions in the block pull thread

This can happen when the daemon exits, which would also cause
the wallet to crash via unhandled exception
release-v0.4.0.1
moneromooo-monero 9 years ago
parent af2106122d
commit 92ef6b54fe
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3

@ -648,21 +648,30 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched)
refresh(start_height, blocks_fetched, received_money); refresh(start_height, blocks_fetched, received_money);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks) void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, bool &error)
{ {
// prepend the last 3 blocks, should be enough to guard against a block or two's reorg error = false;
cryptonote::block bl;
std::list<cryptonote::block_complete_entry>::const_reverse_iterator i = prev_blocks.rbegin(); try
for (size_t n = 0; n < std::min((size_t)3, prev_blocks.size()); ++n)
{ {
bool ok = cryptonote::parse_and_validate_block_from_blob(i->block, bl); // prepend the last 3 blocks, should be enough to guard against a block or two's reorg
THROW_WALLET_EXCEPTION_IF(!ok, error::block_parse_error, i->block); cryptonote::block bl;
short_chain_history.push_front(cryptonote::get_block_hash(bl)); std::list<cryptonote::block_complete_entry>::const_reverse_iterator i = prev_blocks.rbegin();
++i; for (size_t n = 0; n < std::min((size_t)3, prev_blocks.size()); ++n)
} {
bool ok = cryptonote::parse_and_validate_block_from_blob(i->block, bl);
THROW_WALLET_EXCEPTION_IF(!ok, error::block_parse_error, i->block);
short_chain_history.push_front(cryptonote::get_block_hash(bl));
++i;
}
// pull the new blocks // pull the new blocks
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks); pull_blocks(start_height, blocks_start_height, short_chain_history, blocks);
}
catch(...)
{
error = true;
}
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money) void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
@ -689,7 +698,8 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
// pull the next set of blocks while we're processing the current one // pull the next set of blocks while we're processing the current one
uint64_t next_blocks_start_height; uint64_t next_blocks_start_height;
std::list<cryptonote::block_complete_entry> next_blocks; std::list<cryptonote::block_complete_entry> next_blocks;
pull_thread = std::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks);}); bool error = false;
pull_thread = std::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, error);});
process_blocks(blocks_start_height, blocks, added_blocks); process_blocks(blocks_start_height, blocks, added_blocks);
blocks_fetched += added_blocks; blocks_fetched += added_blocks;
@ -700,6 +710,12 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
// switch to the new blocks from the daemon // switch to the new blocks from the daemon
blocks_start_height = next_blocks_start_height; blocks_start_height = next_blocks_start_height;
blocks = next_blocks; blocks = next_blocks;
// handle error from async fetching thread
if (error)
{
throw std::runtime_error("proxy exception in refresh thread");
}
} }
catch (const std::exception&) catch (const std::exception&)
{ {

@ -359,7 +359,7 @@ namespace tools
bool is_transfer_unlocked(const transfer_details& td) const; bool is_transfer_unlocked(const transfer_details& td) const;
bool clear(); bool clear();
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<cryptonote::block_complete_entry> &blocks); void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<cryptonote::block_complete_entry> &blocks);
void pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks); void pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, bool &error);
void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, uint64_t& blocks_added); void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, uint64_t& blocks_added);
uint64_t select_transfers(uint64_t needed_money, bool add_dust, uint64_t dust, std::list<transfer_container::iterator>& selected_transfers); uint64_t select_transfers(uint64_t needed_money, bool add_dust, uint64_t dust, std::list<transfer_container::iterator>& selected_transfers);
bool prepare_file_names(const std::string& file_path); bool prepare_file_names(const std::string& file_path);

Loading…
Cancel
Save