diff options
| author | bors <bors@rust-lang.org> | 2014-03-15 23:01:24 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-03-15 23:01:24 -0700 |
| commit | f6fcdbb68718380beca798d087c46152cad0949c (patch) | |
| tree | c6b7fd10bb869fba19561852cf4eb286b0f96a4f /src/libstd/rt | |
| parent | abd844e4df068196d1150ac39d596f73e210d95d (diff) | |
| parent | 0015cab1fd7b4b47030c808a825bb5594cc1d4ac (diff) | |
| download | rust-f6fcdbb68718380beca798d087c46152cad0949c.tar.gz rust-f6fcdbb68718380beca798d087c46152cad0949c.zip | |
auto merge of #12791 : alexcrichton/rust/liblog, r=brson
The rationale and modifications can be found in the first commit message. This does make logging a bit more painful to use initially because it involves a feature gate and some `phase` attributes, but I think it may be reasonable to not require the `phase` attribute for loading `macro_rules!` macros because defining them will still be gated.
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/backtrace.rs | 22 | ||||
| -rw-r--r-- | src/libstd/rt/crate_map.rs | 99 | ||||
| -rw-r--r-- | src/libstd/rt/logging.rs | 314 | ||||
| -rw-r--r-- | src/libstd/rt/mod.rs | 4 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 5 | ||||
| -rw-r--r-- | src/libstd/rt/unwind.rs | 2 |
6 files changed, 36 insertions, 410 deletions
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 831f6c73e35..bc75a98e085 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -16,15 +16,31 @@ use from_str::from_str; use io::{IoResult, Writer}; use iter::Iterator; use option::{Some, None}; +use os; use result::{Ok, Err}; use str::StrSlice; +use sync::atomics; pub use self::imp::write; -// This function is defined in this module so that the way to enable logging of -// backtraces has the word 'backtrace' in it: std::rt::backtrace. +// For now logging is turned off by default, and this function checks to see +// whether the magical environment variable is present to see if it's turned on. pub fn log_enabled() -> bool { - log_enabled!(::logging::DEBUG) + static mut ENABLED: atomics::AtomicInt = atomics::INIT_ATOMIC_INT; + unsafe { + match ENABLED.load(atomics::SeqCst) { + 1 => return false, + 2 => return true, + _ => {} + } + } + + let val = match os::getenv("RUST_BACKTRACE") { + Some(..) => 2, + None => 1, + }; + unsafe { ENABLED.store(val, atomics::SeqCst); } + val == 2 } #[cfg(target_word_size = "64")] static HEX_WIDTH: uint = 18; diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index ff54a80ce99..c6d5a80208b 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -9,13 +9,14 @@ // except according to those terms. use cast; -use cmp::TotalOrd; -use container::MutableSet; -use iter::Iterator; use option::{Some, None, Option}; use ptr::RawPtr; use rt::rtio::EventLoop; -use vec::{ImmutableVector, OwnedVector}; + +#[cfg(stage0)] use cmp::TotalOrd; +#[cfg(stage0)] use container::MutableSet; +#[cfg(stage0)] use iter::Iterator; +#[cfg(stage0)] use vec::{ImmutableVector, OwnedVector}; // Need to tell the linker on OS X to not barf on undefined symbols // and instead look them up at runtime, which we need to resolve @@ -24,17 +25,24 @@ use vec::{ImmutableVector, OwnedVector}; #[link_args = "-Wl,-U,__rust_crate_map_toplevel"] extern {} +#[cfg(stage0)] pub struct ModEntry<'a> { name: &'a str, log_level: *mut u32 } +#[cfg(stage0)] pub struct CrateMap<'a> { version: i32, entries: &'a [ModEntry<'a>], children: &'a [&'a CrateMap<'a>], event_loop_factory: Option<fn() -> ~EventLoop>, } +#[cfg(not(stage0))] +pub struct CrateMap<'a> { + version: i32, + event_loop_factory: Option<fn() -> ~EventLoop>, +} // When working on android, apparently weak symbols don't work so well for // finding the crate map, and neither does dlopen + dlsym. This is mainly a @@ -114,6 +122,7 @@ pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { } } +#[cfg(stage0)] fn version(crate_map: &CrateMap) -> i32 { match crate_map.version { 2 => return 2, @@ -121,6 +130,7 @@ fn version(crate_map: &CrateMap) -> i32 { } } +#[cfg(stage0)] fn do_iter_crate_map<'a>( crate_map: &'a CrateMap<'a>, f: |&'a ModEntry<'a>|, @@ -149,87 +159,8 @@ fn do_iter_crate_map<'a>( } /// Iterates recursively over `crate_map` and all child crate maps +#[cfg(stage0)] pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: |&'a ModEntry<'a>|) { let mut v = ~[]; do_iter_crate_map(crate_map, f, &mut v); } - -#[cfg(test)] -mod tests { - use option::None; - use rt::crate_map::{CrateMap, ModEntry, iter_crate_map}; - - #[test] - fn iter_crate_map_duplicates() { - let mut level3: u32 = 3; - - let entries = [ - ModEntry { name: "c::m1", log_level: &mut level3}, - ]; - - let child_crate = CrateMap { - version: 2, - entries: entries, - children: &[], - event_loop_factory: None, - }; - - let root_crate = CrateMap { - version: 2, - entries: &[], - children: &[&child_crate, &child_crate], - event_loop_factory: None, - }; - - let mut cnt = 0; - unsafe { - iter_crate_map(&root_crate, |entry| { - assert!(*entry.log_level == 3); - cnt += 1; - }); - assert!(cnt == 1); - } - } - - #[test] - fn iter_crate_map_follow_children() { - let mut level2: u32 = 2; - let mut level3: u32 = 3; - let child_crate2 = CrateMap { - version: 2, - entries: &[ - ModEntry { name: "c::m1", log_level: &mut level2}, - ModEntry { name: "c::m2", log_level: &mut level3}, - ], - children: &[], - event_loop_factory: None, - }; - - let child_crate1 = CrateMap { - version: 2, - entries: &[ - ModEntry { name: "t::f1", log_level: &mut 1}, - ], - children: &[&child_crate2], - event_loop_factory: None, - }; - - let root_crate = CrateMap { - version: 2, - entries: &[ - ModEntry { name: "t::f2", log_level: &mut 0}, - ], - children: &[&child_crate1], - event_loop_factory: None, - }; - - let mut cnt = 0; - unsafe { - iter_crate_map(&root_crate, |entry| { - assert!(*entry.log_level == cnt); - cnt += 1; - }); - assert!(cnt == 4); - } - } -} diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs deleted file mode 100644 index aa024a53b89..00000000000 --- a/src/libstd/rt/logging.rs +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use container::Container; -use from_str::from_str; -use iter::Iterator; -use libc::exit; -use option::{Some, None, Option}; -use os; -use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map}; -use str::{Str, StrSlice}; -use vec::{ImmutableVector, MutableTotalOrdVector, OwnedVector}; -use vec_ng::Vec; - -struct LogDirective<'a> { - name: Option<&'a str>, - level: u32 -} - -static MAX_LOG_LEVEL: u32 = 255; -static DEFAULT_LOG_LEVEL: u32 = 1; -static log_level_names : &'static[&'static str] = &'static["error", "warn", "info", "debug"]; - -/// Parse an individual log level that is either a number or a symbolic log level -fn parse_log_level(level: &str) -> Option<u32> { - let num = from_str::<u32>(level); - let mut log_level; - match num { - Some(num) => { - if num < MAX_LOG_LEVEL { - log_level = Some(num); - } else { - log_level = Some(MAX_LOG_LEVEL); - } - } - _ => { - let position = log_level_names.iter().position(|&name| name == level); - match position { - Some(position) => { - log_level = Some(::cmp::min(MAX_LOG_LEVEL, (position + 1) as u32)) - }, - _ => { - log_level = None; - } - } - } - } - log_level -} - -/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1") -/// and return a vector with log directives. -/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::). -/// Also supports string log levels of error, warn, info, and debug -fn parse_logging_spec<'a>(spec: &'a str) -> Vec<LogDirective<'a>> { - let mut dirs = Vec::new(); - for s in spec.split(',') { - if s.len() == 0 { continue } - let mut parts = s.split('='); - let log_level; - let name; - match (parts.next(), parts.next(), parts.next()) { - (Some(part0), None, None) => { - //if the single argument is a log-level string or number, - //treat that as a global fallback - let possible_log_level = parse_log_level(part0); - match possible_log_level { - Some(num) => { - name = None; - log_level = num; - }, - None => { - log_level = MAX_LOG_LEVEL; - name = Some(part0); - } - } - } - (Some(part0), Some(part1), None) => { - let possible_log_level = parse_log_level(part1); - match possible_log_level { - Some(num) => { - name = Some(part0); - log_level = num; - }, - _ => { - rterrln!("warning: invalid logging spec '{}', \ - ignoring it", part1); - continue - } - } - }, - _ => { - rterrln!("warning: invalid logging spec '{}', \ - ignoring it", s); - continue - } - } - dirs.push(LogDirective { name: name, level: log_level }); - } - return dirs; -} - -/// Set the log level of an entry in the crate map depending on the vector -/// of log directives -fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 { - let mut new_lvl: u32 = DEFAULT_LOG_LEVEL; - let mut longest_match = -1i; - for dir in dirs.iter() { - match dir.name { - None => { - if longest_match == -1 { - longest_match = 0; - new_lvl = dir.level; - } - } - Some(ref dir_name) => { - let name = entry.name; - let len = dir_name.len() as int; - if name.starts_with(*dir_name) && - len >= longest_match { - longest_match = len; - new_lvl = dir.level; - } - } - }; - } - unsafe { *entry.log_level = new_lvl; } - if longest_match >= 0 { return 1; } else { return 0; } -} - -/// Set log level for every entry in crate_map according to the sepecification -/// in settings -fn update_log_settings(crate_map: &CrateMap, settings: &str) { - if settings == "::help" || settings == "?" { - rterrln!("\nCrate log map:\n"); - - let mut entries = Vec::new(); - iter_crate_map(crate_map, |entry| entries.push(entry.name)); - entries.as_mut_slice().sort(); - - for name in entries.iter() { - rterrln!(" {}", *name); - } - unsafe { exit(1); } - } - let dirs = parse_logging_spec(settings); - - let mut n_matches: u32 = 0; - iter_crate_map(crate_map, |entry| { - let m = update_entry(dirs.as_slice(), entry); - n_matches += m; - }); - - if n_matches < (dirs.len() as u32) { - rterrln!("warning: got {} RUST_LOG specs but only matched\n\ - {} of them. You may have mistyped a RUST_LOG spec. \n\ - Use RUST_LOG=::help to see the list of crates and modules.\n", - dirs.len(), n_matches); - } -} - -/// Configure logging by traversing the crate map and setting the -/// per-module global logging flags based on the logging spec -pub fn init() { - let log_spec = os::getenv("RUST_LOG"); - match get_crate_map() { - Some(crate_map) => { - match log_spec { - Some(spec) => update_log_settings(crate_map, spec.as_slice()), - None => update_log_settings(crate_map, ""), - } - }, - _ => { - match log_spec { - Some(_) => { - rterrln!("warning: RUST_LOG set, but no crate map found."); - }, - None => {} - } - } - } -} - -// Tests for parse_logging_spec() -#[test] -fn parse_logging_spec_valid() { - let dirs = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4"); - let dirs = dirs.as_slice(); - assert_eq!(dirs.len(), 3); - assert_eq!(dirs[0].name, Some("crate1::mod1")); - assert_eq!(dirs[0].level, 1); - - assert_eq!(dirs[1].name, Some("crate1::mod2")); - assert_eq!(dirs[1].level, MAX_LOG_LEVEL); - - assert_eq!(dirs[2].name, Some("crate2")); - assert_eq!(dirs[2].level, 4); -} - -#[test] -fn parse_logging_spec_invalid_crate() { - // test parse_logging_spec with multiple = in specification - let dirs = parse_logging_spec("crate1::mod1=1=2,crate2=4"); - let dirs = dirs.as_slice(); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2")); - assert_eq!(dirs[0].level, 4); -} - -#[test] -fn parse_logging_spec_invalid_log_level() { - // test parse_logging_spec with 'noNumber' as log level - let dirs = parse_logging_spec("crate1::mod1=noNumber,crate2=4"); - let dirs = dirs.as_slice(); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2")); - assert_eq!(dirs[0].level, 4); -} - -#[test] -fn parse_logging_spec_string_log_level() { - // test parse_logging_spec with 'warn' as log level - let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=warn"); - let dirs = dirs.as_slice(); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2")); - assert_eq!(dirs[0].level, 2); -} - -#[test] -fn parse_logging_spec_global() { - // test parse_logging_spec with no crate - let dirs = parse_logging_spec("warn,crate2=4"); - let dirs = dirs.as_slice(); - assert_eq!(dirs.len(), 2); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, 2); - assert_eq!(dirs[1].name, Some("crate2")); - assert_eq!(dirs[1].level, 4); -} - -// Tests for update_entry -#[test] -fn update_entry_match_full_path() { - let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 }, - LogDirective { name: Some("crate2"), level: 3 }]; - let mut level = 0; - { - let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level }; - assert_eq!(update_entry(dirs, entry), 1); - } - assert_eq!(level, 2); -} - -#[test] -fn update_entry_no_match() { - let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 }, - LogDirective { name: Some("crate2"), level: 3 }]; - let mut level = 0; - { - let entry = &ModEntry { name: "crate3::mod1", log_level: &mut level }; - assert_eq!(update_entry(dirs, entry), 0); - } - assert_eq!(level, DEFAULT_LOG_LEVEL); -} - -#[test] -fn update_entry_match_beginning() { - let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 }, - LogDirective { name: Some("crate2"), level: 3 }]; - let mut level = 0; - { - let entry= &ModEntry {name: "crate2::mod1", log_level: &mut level}; - assert_eq!(update_entry(dirs, entry), 1); - } - assert_eq!(level, 3); -} - -#[test] -fn update_entry_match_beginning_longest_match() { - let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 }, - LogDirective { name: Some("crate2"), level: 3 }, - LogDirective { name: Some("crate2::mod"), level: 4 }]; - let mut level = 0; - { - let entry = &ModEntry { name: "crate2::mod1", log_level: &mut level }; - assert_eq!(update_entry(dirs, entry), 1); - } - assert_eq!(level, 4); -} - -#[test] -fn update_entry_match_default() { - let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 }, - LogDirective { name: None, level: 3 }]; - let mut level = 0; - { - let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level }; - assert_eq!(update_entry(dirs, entry), 1); - } - assert_eq!(level, 2); - { - let entry = &ModEntry { name: "crate2::mod2", log_level: &mut level }; - assert_eq!(update_entry(dirs, entry), 1); - } - assert_eq!(level, 3); -} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index a58826daa49..84e547619df 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -104,9 +104,6 @@ pub mod env; /// The local, managed heap pub mod local_heap; -/// The Logger trait and implementations -pub mod logging; - /// Crate map pub mod crate_map; @@ -183,7 +180,6 @@ pub fn init(argc: int, argv: **u8) { unsafe { args::init(argc, argv); env::init(); - logging::init(); local_ptr::init(); at_exit_imp::init(); } diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 86e69560e9d..8c617c1b59b 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -21,7 +21,6 @@ use comm::Sender; use io::Writer; use iter::{Iterator, Take}; use local_data; -use logging::Logger; use ops::Drop; use option::{Option, Some, None}; use prelude::drop; @@ -51,7 +50,6 @@ pub struct Task { destroyed: bool, name: Option<SendStr>, - logger: Option<~Logger>, stdout: Option<~Writer>, stderr: Option<~Writer>, @@ -95,7 +93,6 @@ impl Task { death: Death::new(), destroyed: false, name: None, - logger: None, stdout: None, stderr: None, imp: None, @@ -129,11 +126,9 @@ impl Task { #[allow(unused_must_use)] fn close_outputs() { let mut task = Local::borrow(None::<Task>); - let logger = task.get().logger.take(); let stderr = task.get().stderr.take(); let stdout = task.get().stdout.take(); drop(task); - drop(logger); // loggers are responsible for flushing match stdout { Some(mut w) => { w.flush(); }, None => {} } match stderr { Some(mut w) => { w.flush(); }, None => {} } } diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 3a06075ce48..7f54b8b3320 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -398,6 +398,8 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! { if backtrace::log_enabled() { let mut err = ::rt::util::Stderr; let _err = backtrace::write(&mut err); + } else { + rterrln!("run with `RUST_BACKTRACE=1` to see a backtrace"); } unsafe { intrinsics::abort() } } |
