From 05a5a7fdeaa57b5a3f256d83c518c860db8043f9 Mon Sep 17 00:00:00 2001 From: Andrew Fitzgerald Date: Mon, 17 Jun 2024 10:05:42 -0500 Subject: [PATCH] fx race condition on vote count --- .../banking_stage/latest_unprocessed_votes.rs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/core/src/banking_stage/latest_unprocessed_votes.rs b/core/src/banking_stage/latest_unprocessed_votes.rs index 44ed870e3fb86b..707142360b81df 100644 --- a/core/src/banking_stage/latest_unprocessed_votes.rs +++ b/core/src/banking_stage/latest_unprocessed_votes.rs @@ -203,7 +203,10 @@ impl LatestUnprocessedVotes { let pubkey = vote.pubkey(); let slot = vote.slot(); let timestamp = vote.timestamp(); - if let Some(latest_vote) = self.get_entry(pubkey) { + + let with_latest_vote = |latest_vote: &RwLock, + vote: LatestValidatorVotePacket| + -> Option { let (latest_slot, latest_timestamp) = latest_vote .read() .map(|vote| (vote.slot(), vote.timestamp())) @@ -225,15 +228,24 @@ impl LatestUnprocessedVotes { } } } - return Some(vote); - } + Some(vote) + }; - // Should have low lock contention because this is only hit on the first few blocks of startup - // and when a new vote account starts voting. - let mut latest_votes_per_pubkey = self.latest_votes_per_pubkey.write().unwrap(); - latest_votes_per_pubkey.insert(pubkey, Arc::new(RwLock::new(vote))); - self.num_unprocessed_votes.fetch_add(1, Ordering::Relaxed); - None + if let Some(latest_vote) = self.get_entry(pubkey) { + with_latest_vote(&latest_vote, vote) + } else { + // Grab write-lock to insert new vote. + match self.latest_votes_per_pubkey.write().unwrap().entry(pubkey) { + std::collections::hash_map::Entry::Occupied(entry) => { + with_latest_vote(entry.get(), vote) + } + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(Arc::new(RwLock::new(vote))); + self.num_unprocessed_votes.fetch_add(1, Ordering::Relaxed); + None + } + } + } } #[cfg(test)]