error_chain/
backtrace.rs
1pub use self::imp::{Backtrace, InternalBacktrace};
2
3#[cfg(feature = "backtrace")]
4mod imp {
5 extern crate backtrace;
6
7 use std::cell::UnsafeCell;
8 use std::env;
9 use std::fmt;
10 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
11 use std::sync::{Arc, Mutex};
12
13 #[doc(hidden)]
15 #[derive(Clone)]
16 pub struct InternalBacktrace {
17 backtrace: Option<Arc<MaybeResolved>>,
18 }
19
20 struct MaybeResolved {
21 resolved: Mutex<bool>,
22 backtrace: UnsafeCell<Backtrace>,
23 }
24
25 unsafe impl Send for MaybeResolved {}
26 unsafe impl Sync for MaybeResolved {}
27
28 pub use self::backtrace::Backtrace;
29
30 impl InternalBacktrace {
31 #[doc(hidden)]
35 pub fn new() -> InternalBacktrace {
36 static ENABLED: AtomicUsize = ATOMIC_USIZE_INIT;
37
38 match ENABLED.load(Ordering::SeqCst) {
39 0 => {
40 let enabled = match env::var_os("RUST_BACKTRACE") {
41 Some(ref val) if val != "0" => true,
42 _ => false,
43 };
44 ENABLED.store(enabled as usize + 1, Ordering::SeqCst);
45 if !enabled {
46 return InternalBacktrace { backtrace: None }
47 }
48 }
49 1 => return InternalBacktrace { backtrace: None },
50 _ => {}
51 }
52
53 InternalBacktrace {
54 backtrace: Some(Arc::new(MaybeResolved {
55 resolved: Mutex::new(false),
56 backtrace: UnsafeCell::new(Backtrace::new_unresolved()),
57 })),
58 }
59 }
60
61 #[doc(hidden)]
63 pub fn as_backtrace(&self) -> Option<&Backtrace> {
64 let bt = match self.backtrace {
65 Some(ref bt) => bt,
66 None => return None,
67 };
68 let mut resolved = bt.resolved.lock().unwrap();
69 unsafe {
70 if !*resolved {
71 (*bt.backtrace.get()).resolve();
72 *resolved = true;
73 }
74 Some(&*bt.backtrace.get())
75 }
76 }
77 }
78
79 impl fmt::Debug for InternalBacktrace {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 f.debug_struct("InternalBacktrace")
82 .field("backtrace", &self.as_backtrace())
83 .finish()
84 }
85 }
86}
87
88#[cfg(not(feature = "backtrace"))]
89mod imp {
90 pub type Backtrace = ();
92
93 #[doc(hidden)]
95 #[derive(Clone, Debug)]
96 pub struct InternalBacktrace {}
97
98 impl InternalBacktrace {
99 #[doc(hidden)]
101 pub fn new() -> InternalBacktrace {
102 InternalBacktrace {}
103 }
104
105 #[doc(hidden)]
107 pub fn as_backtrace(&self) -> Option<&Backtrace> {
108 None
109 }
110 }
111}