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 static DEADLOCK_DETECTION_LOCK: Mutex<()> = crate::const_mutex(()); 50 check_deadlock() -> bool51 fn check_deadlock() -> bool { 52 use parking_lot_core::deadlock::check_deadlock; 53 !check_deadlock().is_empty() 54 } 55 56 #[test] test_mutex_deadlock()57 fn test_mutex_deadlock() { 58 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 59 60 let m1: Arc<Mutex<()>> = Default::default(); 61 let m2: Arc<Mutex<()>> = Default::default(); 62 let m3: Arc<Mutex<()>> = Default::default(); 63 let b = Arc::new(Barrier::new(4)); 64 65 let m1_ = m1.clone(); 66 let m2_ = m2.clone(); 67 let m3_ = m3.clone(); 68 let b1 = b.clone(); 69 let b2 = b.clone(); 70 let b3 = b.clone(); 71 72 assert!(!check_deadlock()); 73 74 let _t1 = thread::spawn(move || { 75 let _g = m1.lock(); 76 b1.wait(); 77 let _ = m2_.lock(); 78 }); 79 80 let _t2 = thread::spawn(move || { 81 let _g = m2.lock(); 82 b2.wait(); 83 let _ = m3_.lock(); 84 }); 85 86 let _t3 = thread::spawn(move || { 87 let _g = m3.lock(); 88 b3.wait(); 89 let _ = m1_.lock(); 90 }); 91 92 assert!(!check_deadlock()); 93 94 b.wait(); 95 sleep(Duration::from_millis(50)); 96 assert!(check_deadlock()); 97 98 assert!(!check_deadlock()); 99 } 100 101 #[test] test_mutex_deadlock_reentrant()102 fn test_mutex_deadlock_reentrant() { 103 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 104 105 let m1: Arc<Mutex<()>> = Default::default(); 106 107 assert!(!check_deadlock()); 108 109 let _t1 = thread::spawn(move || { 110 let _g = m1.lock(); 111 let _ = m1.lock(); 112 }); 113 114 sleep(Duration::from_millis(50)); 115 assert!(check_deadlock()); 116 117 assert!(!check_deadlock()); 118 } 119 120 #[test] test_remutex_deadlock()121 fn test_remutex_deadlock() { 122 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 123 124 let m1: Arc<ReentrantMutex<()>> = Default::default(); 125 let m2: Arc<ReentrantMutex<()>> = Default::default(); 126 let m3: Arc<ReentrantMutex<()>> = Default::default(); 127 let b = Arc::new(Barrier::new(4)); 128 129 let m1_ = m1.clone(); 130 let m2_ = m2.clone(); 131 let m3_ = m3.clone(); 132 let b1 = b.clone(); 133 let b2 = b.clone(); 134 let b3 = b.clone(); 135 136 assert!(!check_deadlock()); 137 138 let _t1 = thread::spawn(move || { 139 let _g = m1.lock(); 140 let _g = m1.lock(); 141 b1.wait(); 142 let _ = m2_.lock(); 143 }); 144 145 let _t2 = thread::spawn(move || { 146 let _g = m2.lock(); 147 let _g = m2.lock(); 148 b2.wait(); 149 let _ = m3_.lock(); 150 }); 151 152 let _t3 = thread::spawn(move || { 153 let _g = m3.lock(); 154 let _g = m3.lock(); 155 b3.wait(); 156 let _ = m1_.lock(); 157 }); 158 159 assert!(!check_deadlock()); 160 161 b.wait(); 162 sleep(Duration::from_millis(50)); 163 assert!(check_deadlock()); 164 165 assert!(!check_deadlock()); 166 } 167 168 #[test] test_rwlock_deadlock()169 fn test_rwlock_deadlock() { 170 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 171 172 let m1: Arc<RwLock<()>> = Default::default(); 173 let m2: Arc<RwLock<()>> = Default::default(); 174 let m3: Arc<RwLock<()>> = Default::default(); 175 let b = Arc::new(Barrier::new(4)); 176 177 let m1_ = m1.clone(); 178 let m2_ = m2.clone(); 179 let m3_ = m3.clone(); 180 let b1 = b.clone(); 181 let b2 = b.clone(); 182 let b3 = b.clone(); 183 184 assert!(!check_deadlock()); 185 186 let _t1 = thread::spawn(move || { 187 let _g = m1.read(); 188 b1.wait(); 189 let _g = m2_.write(); 190 }); 191 192 let _t2 = thread::spawn(move || { 193 let _g = m2.read(); 194 b2.wait(); 195 let _g = m3_.write(); 196 }); 197 198 let _t3 = thread::spawn(move || { 199 let _g = m3.read(); 200 b3.wait(); 201 let _ = m1_.write(); 202 }); 203 204 assert!(!check_deadlock()); 205 206 b.wait(); 207 sleep(Duration::from_millis(50)); 208 assert!(check_deadlock()); 209 210 assert!(!check_deadlock()); 211 } 212 213 #[cfg(rwlock_deadlock_detection_not_supported)] 214 #[test] test_rwlock_deadlock_reentrant()215 fn test_rwlock_deadlock_reentrant() { 216 let _guard = DEADLOCK_DETECTION_LOCK.lock(); 217 218 let m1: Arc<RwLock<()>> = Default::default(); 219 220 assert!(!check_deadlock()); 221 222 let _t1 = thread::spawn(move || { 223 let _g = m1.read(); 224 let _ = m1.write(); 225 }); 226 227 sleep(Duration::from_millis(50)); 228 assert!(check_deadlock()); 229 230 assert!(!check_deadlock()); 231 } 232 } 233