From 448d0228b2f8e4266eb03811b391dd153447435f Mon Sep 17 00:00:00 2001 From: Seulgi Kim Date: Fri, 26 Apr 2019 13:31:53 +0900 Subject: [PATCH 1/2] Make VerificationQueue join the child threads on drop --- core/src/verification/queue/mod.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/core/src/verification/queue/mod.rs b/core/src/verification/queue/mod.rs index ec59d51670..79402d8553 100644 --- a/core/src/verification/queue/mod.rs +++ b/core/src/verification/queue/mod.rs @@ -67,14 +67,12 @@ pub struct VerificationQueue { engine: Arc, verification: Arc>, processing: RwLock>, // hash to score - #[allow(dead_code)] deleting: Arc, ready_signal: Arc, total_score: RwLock, #[allow(dead_code)] empty: Arc, more_to_verify: Arc, - #[allow(dead_code)] verifier_handles: Vec>, max_queue_size: usize, max_mem_use: usize, @@ -161,11 +159,20 @@ impl VerificationQueue { let more_to_verify = more_to_verify.clone(); let ready_signal = ready_signal.clone(); let empty = empty.clone(); + let deleting = Arc::clone(&deleting); let handle = thread::Builder::new() .name(format!("Verifier #{}", i)) .spawn(move || { - VerificationQueue::verify(&verification, &*engine, &*ready_signal, &*empty, &*more_to_verify, i) + VerificationQueue::verify( + &verification, + &*engine, + &*ready_signal, + &*empty, + &*more_to_verify, + &*deleting, + i, + ) }) .expect("Failed to create verifier thread."); verifier_handles.push(handle); @@ -192,6 +199,7 @@ impl VerificationQueue { ready_signal: &QueueSignal, empty: &SCondvar, more_to_verify: &SCondvar, + deleting: &AtomicBool, _id: usize, ) { loop { @@ -204,9 +212,15 @@ impl VerificationQueue { } while verification.unverified.lock().is_empty() { + if deleting.load(AtomicOrdering::SeqCst) { + return + } more_to_verify_mutex = more_to_verify.wait(more_to_verify_mutex).unwrap(); } } + if deleting.load(AtomicOrdering::SeqCst) { + return + } // do work. let item = { @@ -474,6 +488,16 @@ impl VerificationQueue { } } +impl Drop for VerificationQueue { + fn drop(&mut self) { + self.deleting.store(true, AtomicOrdering::SeqCst); + self.more_to_verify.notify_all(); + for handle in self.verifier_handles.drain(0..) { + handle.join().unwrap(); + } + } +} + // the internal queue sizes. struct Sizes { unverified: AtomicUsize, From 875f7749bd42ecc48c03088048b12910dbd62637 Mon Sep 17 00:00:00 2001 From: Seulgi Kim Date: Fri, 26 Apr 2019 13:38:38 +0900 Subject: [PATCH 2/2] No need to wait on exit The current code is a hotfix to bypass the crash caused by the db that is open in the other threads. But now you do not have to wait because the previous commits fixed the main thread to wait for joining the child threads. --- codechain/run_node.rs | 15 +-------------- test/src/helper/spawn.ts | 2 -- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/codechain/run_node.rs b/codechain/run_node.rs index ddefd40697..3094d328d9 100644 --- a/codechain/run_node.rs +++ b/codechain/run_node.rs @@ -14,11 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use std::env; use std::fs; use std::path::Path; use std::sync::{Arc, Weak}; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use std::time::{SystemTime, UNIX_EPOCH}; use ccore::{ AccountProvider, AccountProviderError, ChainNotify, Client, ClientConfig, ClientService, EngineInfo, EngineType, @@ -35,7 +34,6 @@ use csync::{BlockSyncExtension, BlockSyncSender, SnapshotService, TransactionSyn use ctimer::TimerLoop; use ctrlc::CtrlC; use fdlimit::raise_fd_limit; -use finally_block::finally; use kvdb::KeyValueDB; use kvdb_rocksdb::{Database, DatabaseConfig}; use parking_lot::{Condvar, Mutex}; @@ -226,17 +224,6 @@ pub fn run_node(matches: &ArgMatches) -> Result<(), String> { let config = load_config(matches)?; - // FIXME: It is the hotfix for #348. - // Remove the below code if you find the proper way to solve #348. - let _wait = finally(|| { - const DEFAULT: u64 = 1; - let wait_before_shutdown = env::var_os("WAIT_BEFORE_SHUTDOWN") - .and_then(|sec| sec.into_string().ok()) - .and_then(|sec| sec.parse().ok()) - .unwrap_or(DEFAULT); - ::std::thread::sleep(Duration::from_secs(wait_before_shutdown)); - }); - let scheme = match &config.operating.chain { Some(chain) => chain.scheme()?, None => return Err("chain is not specified".to_string()), diff --git a/test/src/helper/spawn.ts b/test/src/helper/spawn.ts index e74a5bc919..fd9c3089a3 100644 --- a/test/src/helper/spawn.ts +++ b/test/src/helper/spawn.ts @@ -171,8 +171,6 @@ export default class CodeChain { } const useDebugBuild = process.env.NODE_ENV !== "production"; process.env.RUST_LOG = logLevel; - // NOTE: https://github.com/CodeChain-io/codechain/issues/348 - process.env.WAIT_BEFORE_SHUTDOWN = "0"; const baseArgs = [...this.argv, ...argv]; if (disableIpc) {