From 675120687c12812cfd899264d7b3fc5c5b20e989 Mon Sep 17 00:00:00 2001 From: Shelby Doolittle Date: Fri, 29 Oct 2021 17:19:17 -0400 Subject: [PATCH] Don't attempt to cleanup Mutex when threads are deadlocked Closes #173 --- src/rt/mutex.rs | 5 +++++ tests/deadlock.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/deadlock.rs diff --git a/src/rt/mutex.rs b/src/rt/mutex.rs index 7969f01b..219512fa 100644 --- a/src/rt/mutex.rs +++ b/src/rt/mutex.rs @@ -58,6 +58,11 @@ impl Mutex { // Release the lock flag state.lock = None; + // Execution has deadlocked, cleanup does not matter. + if !execution.threads.is_active() { + return; + } + state .synchronize .sync_store(&mut execution.threads, Release); diff --git a/tests/deadlock.rs b/tests/deadlock.rs new file mode 100644 index 00000000..7b3a6bbc --- /dev/null +++ b/tests/deadlock.rs @@ -0,0 +1,38 @@ +// #![deny(warnings, rust_2018_idioms)] + +use loom::sync::Mutex; +use loom::thread; + +use std::rc::Rc; + +#[test] +#[should_panic] +fn two_mutexes_deadlock() { + loom::model(|| { + let a = Rc::new(Mutex::new(1)); + let b = Rc::new(Mutex::new(2)); + + let th1 = { + let a = a.clone(); + let b = b.clone(); + + thread::spawn(move || { + let a_lock = a.lock().unwrap(); + let b_lock = b.lock().unwrap(); + assert_eq!(*a_lock + *b_lock, 3); + }) + }; + let th2 = { + let a = a.clone(); + let b = b.clone(); + + thread::spawn(move || { + let b_lock = b.lock().unwrap(); + let a_lock = a.lock().unwrap(); + assert_eq!(*a_lock + *b_lock, 3); + }) + }; + th1.join().unwrap(); + th2.join().unwrap(); + }); +}