1 //! \[Experimental\] Deadlock detection 2 //! 3 //! This feature is optional and can be enabled via the `deadlock_detection` feature flag. 4 //! 5 //! # Example 6 //! 7 //! ``` 8 //! #[cfg(feature = "deadlock_detection")] 9 //! { // only for #[cfg] 10 //! use std::thread; 11 //! use std::time::Duration; 12 //! use parking_lot::deadlock; 13 //! 14 //! // Create a background thread which checks for deadlocks every 10s 15 //! thread::spawn(move || { 16 //! loop { 17 //! thread::sleep(Duration::from_secs(10)); 18 //! let deadlocks = deadlock::check_deadlock(); 19 //! if deadlocks.is_empty() { 20 //! continue; 21 //! } 22 //! 23 //! println!("{} deadlocks detected", deadlocks.len()); 24 //! for (i, threads) in deadlocks.iter().enumerate() { 25 //! println!("Deadlock #{}", i); 26 //! for t in threads { 27 //! println!("Thread Id {:#?}", t.thread_id()); 28 //! println!("{:#?}", t.backtrace()); 29 //! } 30 //! } 31 //! } 32 //! }); 33 //! } // only for #[cfg] 34 //! ``` 35 36 #[cfg(feature = "deadlock_detection")] 37 pub use parking_lot_core::deadlock::check_deadlock; 38 pub(crate) use parking_lot_core::deadlock::{acquire_resource, release_resource}; 39 40 #[cfg(test)] 41 #[cfg(feature = "deadlock_detection")] 42 mod tests { 43 use crate::{Mutex, ReentrantMutex, RwLock}; 44 use std::sync::{Arc, Barrier}; 45 use std::thread::{self, sleep}; 46 use std::time::Duration; 47 48 // We need to serialize these tests since deadlock detection uses global state 49 lazy_static::lazy_static! { 50 static ref DEADLOCK_DETECTION_LOCK: Mutex<()> = Mutex::new(()); 51 } 52 check_deadlock() -> bool53 fn check_deadlock() -> bool { 54 use parking_lot_core::deadlock::check_deadlock; 55 !check_deadlock().is_empty() 56 } 57 58 #[test] test_mutex_deadlock()59 fn test_mutex_deadlock() { 60 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 61 62 let m1: Arc<Mutex<()>> = Default::default(); 63 let m2: Arc<Mutex<()>> = Default::default(); 64 let m3: Arc<Mutex<()>> = Default::default(); 65 let b = Arc::new(Barrier::new(4)); 66 67 let m1_ = m1.clone(); 68 let m2_ = m2.clone(); 69 let m3_ = m3.clone(); 70 let b1 = b.clone(); 71 let b2 = b.clone(); 72 let b3 = b.clone(); 73 74 assert!(!check_deadlock()); 75 76 let _t1 = thread::spawn(move || { 77 let _g = m1.lock(); 78 b1.wait(); 79 let _ = m2_.lock(); 80 }); 81 82 let _t2 = thread::spawn(move || { 83 let _g = m2.lock(); 84 b2.wait(); 85 let _ = m3_.lock(); 86 }); 87 88 let _t3 = thread::spawn(move || { 89 let _g = m3.lock(); 90 b3.wait(); 91 let _ = m1_.lock(); 92 }); 93 94 assert!(!check_deadlock()); 95 96 b.wait(); 97 sleep(Duration::from_millis(50)); 98 assert!(check_deadlock()); 99 100 assert!(!check_deadlock()); 101 } 102 103 #[test] test_mutex_deadlock_reentrant()104 fn test_mutex_deadlock_reentrant() { 105 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 106 107 let m1: Arc<Mutex<()>> = Default::default(); 108 109 assert!(!check_deadlock()); 110 111 let _t1 = thread::spawn(move || { 112 let _g = m1.lock(); 113 let _ = m1.lock(); 114 }); 115 116 sleep(Duration::from_millis(50)); 117 assert!(check_deadlock()); 118 119 assert!(!check_deadlock()); 120 } 121 122 #[test] test_remutex_deadlock()123 fn test_remutex_deadlock() { 124 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 125 126 let m1: Arc<ReentrantMutex<()>> = Default::default(); 127 let m2: Arc<ReentrantMutex<()>> = Default::default(); 128 let m3: Arc<ReentrantMutex<()>> = Default::default(); 129 let b = Arc::new(Barrier::new(4)); 130 131 let m1_ = m1.clone(); 132 let m2_ = m2.clone(); 133 let m3_ = m3.clone(); 134 let b1 = b.clone(); 135 let b2 = b.clone(); 136 let b3 = b.clone(); 137 138 assert!(!check_deadlock()); 139 140 let _t1 = thread::spawn(move || { 141 let _g = m1.lock(); 142 let _g = m1.lock(); 143 b1.wait(); 144 let _ = m2_.lock(); 145 }); 146 147 let _t2 = thread::spawn(move || { 148 let _g = m2.lock(); 149 let _g = m2.lock(); 150 b2.wait(); 151 let _ = m3_.lock(); 152 }); 153 154 let _t3 = thread::spawn(move || { 155 let _g = m3.lock(); 156 let _g = m3.lock(); 157 b3.wait(); 158 let _ = m1_.lock(); 159 }); 160 161 assert!(!check_deadlock()); 162 163 b.wait(); 164 sleep(Duration::from_millis(50)); 165 assert!(check_deadlock()); 166 167 assert!(!check_deadlock()); 168 } 169 170 #[test] test_rwlock_deadlock()171 fn test_rwlock_deadlock() { 172 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 173 174 let m1: Arc<RwLock<()>> = Default::default(); 175 let m2: Arc<RwLock<()>> = Default::default(); 176 let m3: Arc<RwLock<()>> = Default::default(); 177 let b = Arc::new(Barrier::new(4)); 178 179 let m1_ = m1.clone(); 180 let m2_ = m2.clone(); 181 let m3_ = m3.clone(); 182 let b1 = b.clone(); 183 let b2 = b.clone(); 184 let b3 = b.clone(); 185 186 assert!(!check_deadlock()); 187 188 let _t1 = thread::spawn(move || { 189 let _g = m1.read(); 190 b1.wait(); 191 let _g = m2_.write(); 192 }); 193 194 let _t2 = thread::spawn(move || { 195 let _g = m2.read(); 196 b2.wait(); 197 let _g = m3_.write(); 198 }); 199 200 let _t3 = thread::spawn(move || { 201 let _g = m3.read(); 202 b3.wait(); 203 let _ = m1_.write(); 204 }); 205 206 assert!(!check_deadlock()); 207 208 b.wait(); 209 sleep(Duration::from_millis(50)); 210 assert!(check_deadlock()); 211 212 assert!(!check_deadlock()); 213 } 214 215 #[cfg(rwlock_deadlock_detection_not_supported)] 216 #[test] test_rwlock_deadlock_reentrant()217 fn test_rwlock_deadlock_reentrant() { 218 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 219 220 let m1: Arc<RwLock<()>> = Default::default(); 221 222 assert!(!check_deadlock()); 223 224 let _t1 = thread::spawn(move || { 225 let _g = m1.read(); 226 let _ = m1.write(); 227 }); 228 229 sleep(Duration::from_millis(50)); 230 assert!(check_deadlock()); 231 232 assert!(!check_deadlock()); 233 } 234 } 235