use ckb_logger::debug;
use std::io::{Write, stdin, stdout};
#[cfg(not(feature = "deadlock_detection"))]
pub fn deadlock_detection() {}
#[cfg(feature = "deadlock_detection")]
pub fn deadlock_detection() {
use ckb_channel::select;
use ckb_logger::{info, warn};
use ckb_stop_handler::{new_crossbeam_exit_rx, register_thread};
use ckb_util::parking_lot::deadlock;
use std::{thread, time::Duration};
info!("deadlock_detection enabled");
let dead_lock_jh = thread::spawn({
let ticker = ckb_channel::tick(Duration::from_secs(10));
let stop_rx = new_crossbeam_exit_rx();
move || loop {
select! {
recv(ticker) -> _ => {
let deadlocks = deadlock::check_deadlock();
if deadlocks.is_empty() {
continue;
}
warn!("{} deadlocks detected", deadlocks.len());
for (i, threads) in deadlocks.iter().enumerate() {
warn!("Deadlock #{}", i);
for t in threads {
warn!("Thread Id {:#?}", t.thread_id());
warn!("{:#?}", t.backtrace());
}
}
},
recv(stop_rx) -> _ =>{
info!("deadlock_detection received exit signal, stopped");
return;
}
}
}
});
register_thread("dead_lock_detect", dead_lock_jh);
}
pub fn prompt(msg: &str) -> String {
let stdout = stdout();
let mut stdout = stdout.lock();
let stdin = stdin();
write!(stdout, "{msg}").expect("failed to write prompt to stdout");
stdout.flush().expect("failed to flush stdout");
let mut input = String::new();
let _ = stdin.read_line(&mut input);
input
}
pub fn raise_fd_limit() {
if let Some(limit) = fdlimit::raise_fd_limit() {
debug!("raise_fd_limit newly-increased limit: {}", limit);
}
}