@@ -6,6 +6,8 @@ use std::backtrace::Backtrace;
66use std:: borrow:: Cow ;
77use std:: fmt:: Write ;
88use std:: sync:: Arc ;
9+ use std:: sync:: atomic:: AtomicU8 ;
10+ use std:: sync:: atomic:: Ordering ;
911
1012#[ cfg( feature = "backtraces" ) ]
1113pub type Dep = MutexDep < Arc < Backtrace > > ;
@@ -15,12 +17,44 @@ pub type Dep = MutexDep<()>;
1517// Base message to be reported when cycle is detected
1618const BASE_MESSAGE : & str = "Found cycle in mutex dependency graph:" ;
1719
20+ /// Action to take when a cycle is detected.
21+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
22+ #[ repr( u8 ) ]
23+ pub enum PanicAction {
24+ /// Panic when a cycle is detected.
25+ Panic = 0 ,
26+ /// Log the cycle to stderr but do not panic.
27+ #[ cfg( feature = "experimental" ) ]
28+ Log = 1 ,
29+ }
30+
31+ static PANIC_ACTION : AtomicU8 = AtomicU8 :: new ( 0 ) ;
32+
33+ /// Set the action to take when a cycle is detected.
34+ ///
35+ /// This is useful for incrementally adopting tracing-mutex to a large codebase compiled with
36+ /// `panic=abort`, as it allows you to continue running your program even when a cycle is detected.
37+ #[ cfg( feature = "experimental" ) ]
38+ pub fn set_panic_action ( action : PanicAction ) {
39+ PANIC_ACTION . store ( action as u8 , Ordering :: Relaxed ) ;
40+ }
41+
42+ pub ( crate ) fn report_cycle ( cycle : & [ Dep ] ) {
43+ let message = Dep :: message ( cycle) ;
44+ let action = PANIC_ACTION . load ( Ordering :: Relaxed ) ;
45+ if action == PanicAction :: Panic as u8 {
46+ panic ! ( "{message}" ) ;
47+ } else {
48+ eprintln ! ( "{message}" ) ;
49+ }
50+ }
51+
1852pub trait Reportable : Clone {
1953 /// Capture the current state
2054 fn capture ( ) -> Self ;
2155
2256 /// Format a trace of state for human readable consumption.
23- fn panic_message ( trace : & [ Self ] ) -> Cow < ' static , str > ;
57+ fn message ( trace : & [ Self ] ) -> Cow < ' static , str > ;
2458}
2559
2660#[ derive( Clone ) ]
@@ -35,7 +69,7 @@ impl Reportable for MutexDep<()> {
3569 Self ( ( ) )
3670 }
3771
38- fn panic_message ( _trace : & [ Self ] ) -> Cow < ' static , str > {
72+ fn message ( _trace : & [ Self ] ) -> Cow < ' static , str > {
3973 Cow :: Borrowed ( BASE_MESSAGE )
4074 }
4175}
@@ -52,7 +86,7 @@ impl Reportable for MutexDep<Arc<Backtrace>> {
5286 Self ( Arc :: new ( Backtrace :: capture ( ) ) )
5387 }
5488
55- fn panic_message ( trace : & [ Self ] ) -> Cow < ' static , str > {
89+ fn message ( trace : & [ Self ] ) -> Cow < ' static , str > {
5690 let mut message = format ! ( "{BASE_MESSAGE}\n " ) ;
5791
5892 for entry in trace {
0 commit comments