Skip to main content

lib3h_zombie_actor/
backtwrap.rs

1/// specify whether we want to capture backtraces, and if they should be resolved
2#[derive(Debug, Clone, Copy)]
3pub enum BacktwrapCaptureStrategy {
4    /// don't capture... Backtwrap will contain None
5    DoNotCapture,
6    /// capture unresolved backtraces... you can resolve them before printing
7    CaptureUnresolved,
8    /// capture resolved backtraces... they will have debug symbols
9    CaptureResolved,
10}
11
12use BacktwrapCaptureStrategy::*;
13
14lazy_static! {
15    static ref CAPTURE_STRATEGY: std::sync::Mutex<BacktwrapCaptureStrategy> = {
16        let out = std::sync::Mutex::new(match std::env::var("BACKTRACE_STRATEGY") {
17            Ok(s) => match s.as_str() {
18                "CAPTURE_RESOLVED" => CaptureResolved,
19                "CAPTURE_UNRESOLVED" => CaptureUnresolved,
20                _ => DoNotCapture,
21            },
22            _ => DoNotCapture,
23        });
24        warn!("Using Backtrace Capture Strategy: {:?}", out);
25        out
26    };
27}
28
29/// it seems as though
30/// - linux can caputure resolved backtraces w/o much overhead
31/// - macOs can capture UNresolved backtraces (fn pointers but no debug symbols)
32///   without much overhead
33/// - windows cannot capture backtraces at all without major slowdowns
34#[derive(Shrinkwrap, Debug, Clone)]
35#[shrinkwrap(mutable)]
36pub struct Backtwrap(pub Option<backtrace::Backtrace>);
37
38impl Backtwrap {
39    /// Capture (or doesn't capture) backtraces based on environment variable
40    ///  - default - DoNotCapture
41    ///  - BACKTRACE_STRATEGY=CAPTURE_RESOLVED - CaptureResolved
42    ///  - BACKTRACE_STRATEGY=CAPTURE_UNRESOLVED - CaptureUnresolved
43    pub fn new() -> Self {
44        Self(
45            match *CAPTURE_STRATEGY.lock().expect("failed to lock mutex") {
46                CaptureResolved => Some(backtrace::Backtrace::new()),
47                CaptureUnresolved => Some(backtrace::Backtrace::new_unresolved()),
48                DoNotCapture => None,
49            },
50        )
51    }
52
53    /// get the current capture strategy
54    pub fn get_capture_strategy() -> BacktwrapCaptureStrategy {
55        *CAPTURE_STRATEGY.lock().expect("failed to lock mutex")
56    }
57
58    /// explicitly set the current capture strategy
59    pub fn set_capture_strategy(strategy: BacktwrapCaptureStrategy) {
60        *CAPTURE_STRATEGY.lock().expect("failed to lock mutex") = strategy;
61    }
62}
63
64impl PartialEq for Backtwrap {
65    fn eq(&self, other: &Backtwrap) -> bool {
66        format!("{:?}", self) == format!("{:?}", other)
67    }
68}
69
70impl Eq for Backtwrap {}
71
72impl std::hash::Hash for Backtwrap {
73    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
74        format!("{:?}", self).hash(state);
75    }
76}
77
78impl std::convert::From<backtrace::Backtrace> for Backtwrap {
79    fn from(bt: backtrace::Backtrace) -> Backtwrap {
80        Self(Some(bt))
81    }
82}
83
84impl std::convert::From<Option<backtrace::Backtrace>> for Backtwrap {
85    fn from(bt: Option<backtrace::Backtrace>) -> Backtwrap {
86        Self(bt)
87    }
88}
89
90impl std::convert::From<Backtwrap> for Option<backtrace::Backtrace> {
91    fn from(bt: Backtwrap) -> Option<backtrace::Backtrace> {
92        bt.0
93    }
94}