Hold an accounts_db read lock as briefly as possible to avoid deadlocking

This commit is contained in:
Michael Vines
2019-01-13 10:47:29 -08:00
parent d28b643c84
commit 74e503da92

View File

@ -36,38 +36,40 @@ impl ComputeLeaderConfirmationService {
) -> result::Result<u64, ConfirmationError> { ) -> result::Result<u64, ConfirmationError> {
let mut total_stake = 0; let mut total_stake = 0;
let mut ticks_and_stakes: Vec<(u64, u64)> = { // Hold an accounts_db read lock as briefly as possible, just long enough to collect all
let bank_accounts = bank.accounts.accounts_db.read().unwrap(); // the vote states
// TODO: Doesn't account for duplicates since a single validator could potentially register let vote_states: Vec<VoteProgram> = bank
// multiple vote accounts. Once that is no longer possible (see the TODO in vote_program.rs, .accounts
// process_transaction(), case VoteInstruction::RegisterAccount), this will be more accurate. .accounts_db
// See github issue 1654. .read()
bank_accounts .unwrap()
.accounts .accounts
.values() .values()
.filter_map(|account| { .filter_map(|account| {
// Filter out any accounts that don't belong to the VoteProgram if vote_program::check_id(&account.owner) {
// by returning None if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) {
if vote_program::check_id(&account.owner) { if leader_id != vote_state.node_id {
if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) { return Some(vote_state);
if leader_id == vote_state.node_id {
return None;
}
let validator_stake = bank.get_stake(&vote_state.node_id);
total_stake += validator_stake;
// Filter out any validators that don't have at least one vote
// by returning None
return vote_state
.votes
.back()
.map(|vote| (vote.tick_height, validator_stake));
} }
} }
}
None
})
.collect();
None let mut ticks_and_stakes: Vec<(u64, u64)> = vote_states
}) .iter()
.collect() .filter_map(|vote_state| {
}; let validator_stake = bank.get_stake(&vote_state.node_id);
total_stake += validator_stake;
// Filter out any validators that don't have at least one vote
// by returning None
vote_state
.votes
.back()
.map(|vote| (vote.tick_height, validator_stake))
})
.collect();
let super_majority_stake = (2 * total_stake) / 3; let super_majority_stake = (2 * total_stake) / 3;