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
This commit is contained in:
parent
af2106122d
commit
92ef6b54fe
2 changed files with 31 additions and 15 deletions
|
@ -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();
|
|
||||||
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
|
try
|
||||||
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks);
|
{
|
||||||
|
// prepend the last 3 blocks, should be enough to guard against a block or two's reorg
|
||||||
|
cryptonote::block bl;
|
||||||
|
std::list<cryptonote::block_complete_entry>::const_reverse_iterator i = prev_blocks.rbegin();
|
||||||
|
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_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…
Reference in a new issue