client/common/
shutdown_handler.rs1use std::{
2 sync::{Arc, Weak},
3 thread,
4 time::{Duration, Instant},
5};
6
7use ctrlc::CtrlC;
8use log::{debug, warn};
9use parking_lot::{Condvar, Mutex};
10
11use super::ClientTrait;
12
13pub fn run(
14 this: Box<dyn ClientTrait>, exit_cond_var: Arc<(Mutex<bool>, Condvar)>,
15) -> bool {
16 CtrlC::set_handler({
17 let e = exit_cond_var.clone();
18 move || {
19 *e.0.lock() = true;
20 e.1.notify_all();
21 }
22 });
23
24 let mut lock = exit_cond_var.0.lock();
25 if !*lock {
26 exit_cond_var.1.wait(&mut lock);
27 }
28
29 shutdown(this)
30}
31
32pub fn shutdown(this: Box<dyn ClientTrait>) -> bool {
34 metrics::stop();
36 diem_metrics::stop();
37
38 let (ledger_db, maybe_pos_handler, maybe_blockgen) =
39 this.take_out_components_for_shutdown();
40 drop(this);
41 if let Some(blockgen) = maybe_blockgen {
42 blockgen.stop();
43 drop(blockgen);
44 }
45 let maybe_pos_db = if let Some(pos_handler) = maybe_pos_handler {
46 let maybe_pos_db = pos_handler.stop();
47 drop(pos_handler);
48 maybe_pos_db
49 } else {
50 None
51 };
52
53 let mut graceful = true;
56 graceful &= check_graceful_shutdown(ledger_db);
57 debug!("ledger_db drop: graceful = {}", graceful);
58 if let Some((pos_ledger_db, consensus_db)) = maybe_pos_db {
59 graceful &= check_graceful_shutdown(pos_ledger_db);
60 debug!("pos_ledger_db drop: graceful = {}", graceful);
61 graceful &= check_graceful_shutdown(consensus_db);
62 debug!("consensus_db drop: graceful = {}", graceful);
63 }
64 graceful
65}
66
67fn check_graceful_shutdown<T>(blockdata_manager_weak_ptr: Weak<T>) -> bool {
71 let sleep_duration = Duration::from_secs(1);
72 let warn_timeout = Duration::from_secs(5);
73 let max_timeout = Duration::from_secs(1200);
74 let instant = Instant::now();
75 let mut warned = false;
76 while instant.elapsed() < max_timeout {
77 if blockdata_manager_weak_ptr.upgrade().is_none() {
78 return true;
79 }
80 if !warned && instant.elapsed() > warn_timeout {
81 warned = true;
82 warn!("Shutdown is taking longer than expected.");
83 }
84 thread::sleep(sleep_duration);
85 }
86 eprintln!("Shutdown timeout reached, exiting uncleanly.");
87 false
88}