/rust/registry/src/index.crates.io-1949cf8c6b5b557f/error-chain-0.12.4/src/backtrace.rs
Line | Count | Source |
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)] |
35 | | 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)] |
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"))] |
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)] |
101 | 0 | pub fn new() -> InternalBacktrace { |
102 | 0 | InternalBacktrace {} |
103 | 0 | } |
104 | | |
105 | | /// Returns the internal backtrace |
106 | | #[doc(hidden)] |
107 | 0 | pub fn as_backtrace(&self) -> Option<&Backtrace> { |
108 | 0 | None |
109 | 0 | } |
110 | | } |
111 | | } |