diff --git a/Cargo.lock b/Cargo.lock index 2be5fdfa..541b16ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1030,6 +1030,7 @@ dependencies = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry_sdk", + "parking_lot", "sentry", "sentry-tower", "sentry-tracing", diff --git a/src/main/Cargo.toml b/src/main/Cargo.toml index 6c073c85..7a4dd4d6 100644 --- a/src/main/Cargo.toml +++ b/src/main/Cargo.toml @@ -230,6 +230,7 @@ tracing-opentelemetry.workspace = true tracing-subscriber.workspace = true tracing.workspace = true tracing-journald = { workspace = true, optional = true } +parking_lot.workspace = true [target.'cfg(all(not(target_env = "msvc"), target_os = "linux"))'.dependencies] diff --git a/src/main/deadlock.rs b/src/main/deadlock.rs new file mode 100644 index 00000000..c0da46bf --- /dev/null +++ b/src/main/deadlock.rs @@ -0,0 +1,36 @@ +use std::{thread, time::Duration}; + +/// Runs a loop that checks for deadlocks every 10 seconds. +/// +/// Note that this requires the `deadlock_detection` parking_lot feature to be +/// enabled. +pub(crate) fn deadlock_detection_thread() { + loop { + thread::sleep(Duration::from_secs(10)); + let deadlocks = parking_lot::deadlock::check_deadlock(); + if deadlocks.is_empty() { + continue; + } + + eprintln!("{} deadlocks detected", deadlocks.len()); + for (i, threads) in deadlocks.iter().enumerate() { + eprintln!("Deadlock #{i}"); + for t in threads { + eprintln!("Thread Id {:#?}", t.thread_id()); + eprintln!("{:#?}", t.backtrace()); + } + } + } +} + +/// Spawns the deadlock detection thread. +/// +/// This thread will run in the background and check for deadlocks every 10 +/// seconds. When a deadlock is detected, it will print detailed information to +/// stderr. +pub(crate) fn spawn() { + thread::Builder::new() + .name("deadlock_detector".to_owned()) + .spawn(deadlock_detection_thread) + .expect("failed to spawn deadlock detection thread"); +} diff --git a/src/main/mod.rs b/src/main/mod.rs index a6fd9cef..a430279d 100644 --- a/src/main/mod.rs +++ b/src/main/mod.rs @@ -5,6 +5,7 @@ use std::sync::{Arc, atomic::Ordering}; use conduwuit_core::{debug_info, error}; mod clap; +mod deadlock; mod logging; mod mods; mod panic; @@ -27,6 +28,9 @@ pub fn run() -> Result<()> { } pub fn run_with_args(args: &Args) -> Result<()> { + // Spawn deadlock detection thread + deadlock::spawn(); + let runtime = runtime::new(args)?; let server = Server::new(args, Some(runtime.handle()))?;