1 pub use self::imp::{Backtrace, InternalBacktrace}; 2 3 #[cfg(feature = "backtrace")] 4 mod 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, Ordering}; 11 use std::sync::{Arc, Mutex}; 12 13 /// Internal representation of a backtrace 14 #[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 /// Returns a backtrace of the current call stack if `RUST_BACKTRACE` 32 /// is set to anything but ``0``, and `None` otherwise. This is used 33 /// in the generated error implementations. 34 #[doc(hidden)] new() -> InternalBacktrace35 pub fn new() -> InternalBacktrace { 36 static ENABLED: AtomicUsize = AtomicUsize::new(0); 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 /// Acquire the internal backtrace 62 #[doc(hidden)] as_backtrace(&self) -> Option<&Backtrace>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 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result80 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"))] 89 mod imp { 90 /// Dummy type used when the `backtrace` feature is disabled. 91 pub type Backtrace = (); 92 93 /// Internal representation of a backtrace 94 #[doc(hidden)] 95 #[derive(Clone, Debug)] 96 pub struct InternalBacktrace {} 97 98 impl InternalBacktrace { 99 /// Returns a new backtrace 100 #[doc(hidden)] new() -> InternalBacktrace101 pub fn new() -> InternalBacktrace { 102 InternalBacktrace {} 103 } 104 105 /// Returns the internal backtrace 106 #[doc(hidden)] as_backtrace(&self) -> Option<&Backtrace>107 pub fn as_backtrace(&self) -> Option<&Backtrace> { 108 None 109 } 110 } 111 } 112