Skip to content

Commit 21858cd

Browse files
committed
don't clobber a previously set level filter
There's a bit of a race with the `log` API for initializing because it covers two atomic values. It's possible to observe a logger and attempt to use it before the max level is set. This change doesn't really make that race any racier than it was already, it just prevents the surprising behaviour of clobbering a previously set max level filter even if the logger itself isn't set.
1 parent c1f2c20 commit 21858cd

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ harness = false
3333
name = "log-in-log"
3434
harness = false
3535

36+
[[test]]
37+
name = "init-twice-retains-filter"
38+
harness = false
39+
3640
[features]
3741
default = ["termcolor", "atty", "humantime", "regex"]

src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,8 +646,14 @@ impl Builder {
646646
pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
647647
let logger = self.build();
648648

649-
log::set_max_level(logger.filter());
650-
log::set_boxed_logger(Box::new(logger))
649+
let max_level = logger.filter();
650+
let r = log::set_boxed_logger(Box::new(logger));
651+
652+
if r.is_ok() {
653+
log::set_max_level(max_level);
654+
}
655+
656+
r
651657
}
652658

653659
/// Initializes the global logger with the built env logger.

tests/init-twice-retains-filter.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
extern crate log;
2+
extern crate env_logger;
3+
4+
use std::process;
5+
use std::env;
6+
use std::str;
7+
8+
fn main() {
9+
if env::var("YOU_ARE_TESTING_NOW").is_ok() {
10+
// Init from the env (which should set the max level to `Debug`)
11+
env_logger::init();
12+
13+
assert_eq!(log::LevelFilter::Debug, log::max_level());
14+
15+
// Init again using a different max level
16+
// This shouldn't clobber the level that was previously set
17+
env_logger::Builder::new()
18+
.parse("info")
19+
.try_init()
20+
.unwrap_err();
21+
22+
assert_eq!(log::LevelFilter::Debug, log::max_level());
23+
return
24+
}
25+
26+
let exe = env::current_exe().unwrap();
27+
let out = process::Command::new(exe)
28+
.env("YOU_ARE_TESTING_NOW", "1")
29+
.env("RUST_LOG", "debug")
30+
.output()
31+
.unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
32+
if out.status.success() {
33+
return
34+
}
35+
36+
println!("test failed: {}", out.status);
37+
println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
38+
println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
39+
process::exit(1);
40+
}

0 commit comments

Comments
 (0)