From eef9586c57694142fabf79a50b953185219d42b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 8 Jul 2016 17:19:14 +0200 Subject: [PATCH] Fixing deadlock in miner (#1569) * Fixing deadlock in miner * Adding more comments [ci skip] --- ethcore/src/miner/miner.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 0ee56dccb..7325b4a36 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -301,6 +301,10 @@ impl Miner { let have_work = self.sealing_work.lock().unwrap().peek_last_ref().is_some(); trace!(target: "miner", "enable_and_prepare_sealing: have_work={}", have_work); if !have_work { + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- self.sealing_enabled.store(true, atomic::Ordering::Relaxed); self.prepare_sealing(chain); } @@ -338,6 +342,10 @@ impl MinerService for Miner { fn clear_and_reset(&self, chain: &MiningBlockChainClient) { self.transaction_queue.lock().unwrap().clear(); + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- self.update_sealing(chain); } @@ -493,11 +501,18 @@ impl MinerService for Miner { fn import_external_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec) -> Vec> { - let mut transaction_queue = self.transaction_queue.lock().unwrap(); - let results = self.add_transactions_to_queue(chain, transactions, TransactionOrigin::External, - &mut transaction_queue); + let results = { + let mut transaction_queue = self.transaction_queue.lock().unwrap(); + self.add_transactions_to_queue( + chain, transactions, TransactionOrigin::External, &mut transaction_queue + ) + }; if !results.is_empty() && self.options.reseal_on_external_tx && self.tx_reseal_allowed() { + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- self.update_sealing(chain); } results @@ -531,6 +546,10 @@ impl MinerService for Miner { import }; + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- if imported.is_ok() && self.options.reseal_on_own_tx && self.tx_reseal_allowed() { // Make sure to do it after transaction is imported and lock is droped. // We need to create pending block and enable sealing @@ -625,6 +644,10 @@ impl MinerService for Miner { self.sealing_work.lock().unwrap().reset(); } else { *self.next_allowed_reseal.lock().unwrap() = Instant::now() + self.options.reseal_min_period; + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- self.prepare_sealing(chain); } } @@ -715,6 +738,10 @@ impl MinerService for Miner { }); } + // -------------------------------------------------------------------------- + // | NOTE Code below requires transaction_queue and sealing_work locks. | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- self.update_sealing(chain); } }