From d0d8ac7ebab4d21171f88d47d03205aedd195e5f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2019 18:24:59 -0800 Subject: [PATCH] Fix freeze and register_tick race (#6799) (#6846) automerge --- runtime/src/bank.rs | 9 +++++---- runtime/tests/bank.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 runtime/tests/bank.rs diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index d81bb605f2..a137a39705 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -810,12 +810,13 @@ impl Bank { // TODO: put this assert back in // assert!(!self.is_frozen()); inc_new_counter_debug!("bank-register_tick-registered", 1); + // Grab blockhash lock before incrementing tick height so that replay stage does + // not attempt to freeze after observing the last tick and before blockhash is + // updated + let mut w_blockhash_queue = self.blockhash_queue.write().unwrap(); let current_tick_height = self.tick_height.fetch_add(1, Ordering::Relaxed) as u64; if self.is_block_boundary(current_tick_height + 1) { - self.blockhash_queue - .write() - .unwrap() - .register_hash(hash, &self.fee_calculator); + w_blockhash_queue.register_hash(hash, &self.fee_calculator); } } diff --git a/runtime/tests/bank.rs b/runtime/tests/bank.rs new file mode 100644 index 0000000000..a466bb9d04 --- /dev/null +++ b/runtime/tests/bank.rs @@ -0,0 +1,41 @@ +use solana_runtime::bank::Bank; +use solana_sdk::genesis_block::create_genesis_block; +use solana_sdk::hash::hash; +use solana_sdk::pubkey::Pubkey; +use std::sync::Arc; +use std::thread::Builder; + +#[test] +fn test_race_register_tick_freeze() { + solana_logger::setup(); + + let (mut genesis_block, _) = create_genesis_block(50); + genesis_block.ticks_per_slot = 1; + let p = Pubkey::new_rand(); + let hash = hash(p.as_ref()); + + for _ in 0..1000 { + let bank0 = Arc::new(Bank::new(&genesis_block)); + let bank0_ = bank0.clone(); + let freeze_thread = Builder::new() + .name("freeze".to_string()) + .spawn(move || loop { + if bank0_.tick_height() == bank0_.max_tick_height() { + assert_eq!(bank0_.last_blockhash(), hash); + break; + } + }) + .unwrap(); + + let bank0_ = bank0.clone(); + let register_tick_thread = Builder::new() + .name("register_tick".to_string()) + .spawn(move || { + bank0_.register_tick(&hash); + }) + .unwrap(); + + register_tick_thread.join().unwrap(); + freeze_thread.join().unwrap(); + } +}