Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit f5e2f71

Browse files
eddybYamakaky
authored andcommitted
Cache whether RUST_BACKTRACE is enabled in a relaxed atomic static.
1 parent 8f894a1 commit f5e2f71

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-26
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Unreleased
22

33
- Change last rust version supported to 1.14
4+
- [Cache whether RUST_BACKTRACE is enabled in a relaxed atomic static.](https://github.com/rust-lang-nursery/error-chain/pull/210)
45

56
# 0.11.0-rc.2
67

src/bin/has_backtrace.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//! Exits with exit code 0 if backtraces are disabled and 1 if they are enabled.
2+
//! Used by tests to make sure backtraces are available when they should be. Should not be used
3+
//! outside of the tests.
4+
5+
#[macro_use]
6+
extern crate error_chain;
7+
8+
error_chain! {
9+
errors {
10+
MyError
11+
}
12+
}
13+
14+
fn main() {
15+
let err = Error::from(ErrorKind::MyError);
16+
let has_backtrace = err.backtrace().is_some();
17+
::std::process::exit(has_backtrace as i32);
18+
}

src/lib.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,9 +593,29 @@ impl<'a> Iterator for Iter<'a> {
593593
#[cfg(feature = "backtrace")]
594594
#[doc(hidden)]
595595
pub fn make_backtrace() -> Option<Arc<Backtrace>> {
596-
match std::env::var_os("RUST_BACKTRACE") {
597-
Some(ref val) if val != "0" => Some(Arc::new(Backtrace::new())),
598-
_ => None,
596+
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
597+
598+
// The lowest bit indicates whether the value was computed,
599+
// while the second lowest bit is the actual "enabled" bit.
600+
static BACKTRACE_ENABLED_CACHE: AtomicUsize = ATOMIC_USIZE_INIT;
601+
602+
let enabled = match BACKTRACE_ENABLED_CACHE.load(Ordering::Relaxed) {
603+
0 => {
604+
let enabled = match std::env::var_os("RUST_BACKTRACE") {
605+
Some(ref val) if val != "0" => true,
606+
_ => false
607+
};
608+
let encoded = ((enabled as usize) << 1) | 1;
609+
BACKTRACE_ENABLED_CACHE.store(encoded, Ordering::Relaxed);
610+
enabled
611+
}
612+
encoded => (encoded >> 1) != 0
613+
};
614+
615+
if enabled {
616+
Some(Arc::new(Backtrace::new()))
617+
} else {
618+
None
599619
}
600620
}
601621

tests/tests.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -200,35 +200,29 @@ fn empty() {
200200
#[test]
201201
#[cfg(feature = "backtrace")]
202202
fn has_backtrace_depending_on_env() {
203-
use std::env;
203+
use std::process::Command;
204+
use std::path::Path;
204205

205-
error_chain! {
206-
types {}
207-
links {}
208-
foreign_links {}
209-
errors {
210-
MyError
211-
}
212-
}
213-
214-
let original_value = env::var_os("RUST_BACKTRACE");
206+
let cmd_path = if cfg!(windows) {
207+
Path::new("./target/debug/has_backtrace.exe")
208+
} else {
209+
Path::new("./target/debug/has_backtrace")
210+
};
211+
let mut cmd = Command::new(cmd_path);
215212

216213
// missing RUST_BACKTRACE and RUST_BACKTRACE=0
217-
env::remove_var("RUST_BACKTRACE");
218-
let err = Error::from(ErrorKind::MyError);
219-
assert!(err.backtrace().is_none());
220-
env::set_var("RUST_BACKTRACE", "0");
221-
let err = Error::from(ErrorKind::MyError);
222-
assert!(err.backtrace().is_none());
214+
cmd.env_remove("RUST_BACKTRACE");
215+
assert_eq!(cmd.status().unwrap().code().unwrap(), 0);
216+
217+
cmd.env("RUST_BACKTRACE", "0");
218+
assert_eq!(cmd.status().unwrap().code().unwrap(), 0);
223219

224220
// RUST_BACKTRACE set to anything but 0
225-
env::set_var("RUST_BACKTRACE", "yes");
226-
let err = Error::from(ErrorKind::MyError);
227-
assert!(err.backtrace().is_some());
221+
cmd.env("RUST_BACKTRACE", "yes");
222+
assert_eq!(cmd.status().unwrap().code().unwrap(), 1);
228223

229-
if let Some(var) = original_value {
230-
env::set_var("RUST_BACKTRACE", var);
231-
}
224+
cmd.env("RUST_BACKTRACE", "1");
225+
assert_eq!(cmd.status().unwrap().code().unwrap(), 1);
232226
}
233227

234228
#[test]

0 commit comments

Comments
 (0)