diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-08-28 01:33:48 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-09-25 16:30:05 -0700 |
| commit | eb2b25dd6d38157213742b048fad63fa4ceec691 (patch) | |
| tree | e41f9af78454e8f6641dead395274419d843ab63 /src/libstd | |
| parent | af25f58ac3da45899ed65b3af965150c8a90dcda (diff) | |
| download | rust-eb2b25dd6d38157213742b048fad63fa4ceec691.tar.gz rust-eb2b25dd6d38157213742b048fad63fa4ceec691.zip | |
Refactor the logging system for fewer allocations
This lifts various restrictions on the runtime, for example the character limit when logging a message. Right now the old debug!-style macros still involve allocating (because they use fmt! syntax), but the new debug2! macros don't involve allocating at all (unless the formatter for a type requires allocation.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/logging.rs | 25 | ||||
| -rw-r--r-- | src/libstd/rt/logging.rs | 53 | ||||
| -rw-r--r-- | src/libstd/std.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys.rs | 51 |
4 files changed, 72 insertions, 58 deletions
diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 1a463a499cb..342d0828f82 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -10,11 +10,11 @@ //! Logging +use fmt; use option::*; use os; use rt; use rt::logging::{Logger, StdErrLogger}; -use send_str::SendStrOwned; /// Turns on logging to stdout globally pub fn console_on() { @@ -37,7 +37,17 @@ pub fn console_off() { rt::logging::console_off(); } -fn newsched_log_str(msg: ~str) { +#[cfg(stage0)] +#[doc(hidden)] +pub fn log(_level: u32, s: ~str) { + // this is a terrible approximation, but it gets the job done (for stage0 at + // least) + ::io::println(s); +} + +#[allow(missing_doc)] +#[cfg(not(stage0))] +pub fn log(_level: u32, args: &fmt::Arguments) { use rt::task::Task; use rt::local::Local; @@ -46,20 +56,13 @@ fn newsched_log_str(msg: ~str) { match optional_task { Some(local) => { // Use the available logger - (*local).logger.log(SendStrOwned(msg)); + (*local).logger.log(args); } None => { // There is no logger anywhere, just write to stderr let mut logger = StdErrLogger; - logger.log(SendStrOwned(msg)); + logger.log(args); } } } } - -// XXX: This will change soon to not require an allocation. This is an unstable -// api which should not be used outside of the macros in ext/expand. -#[doc(hidden)] -pub fn log(_level: u32, msg: ~str) { - newsched_log_str(msg); -} diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index 3dbf7a918b7..cfbc53ad34e 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -7,9 +7,12 @@ // <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 fmt; use from_str::from_str; -use libc::{uintptr_t, exit, STDERR_FILENO}; +use libc::{uintptr_t, exit}; use option::{Some, None, Option}; +use rt; use rt::util::dumb_println; use rt::crate_map::{ModEntry, iter_crate_map}; use rt::crate_map::get_crate_map; @@ -18,7 +21,6 @@ use str::raw::from_c_str; use u32; use vec::ImmutableVector; use cast::transmute; -use send_str::{SendStr, SendStrOwned, SendStrStatic}; struct LogDirective { name: Option<~str>, @@ -171,44 +173,33 @@ fn update_log_settings(crate_map: *u8, settings: ~str) { } pub trait Logger { - fn log(&mut self, msg: SendStr); + fn log(&mut self, args: &fmt::Arguments); } pub struct StdErrLogger; impl Logger for StdErrLogger { - fn log(&mut self, msg: SendStr) { - use io::{Writer, WriterUtil}; - - if !should_log_console() { - return; + fn log(&mut self, args: &fmt::Arguments) { + if should_log_console() { + fmt::write(self as &mut rt::io::Writer, args); } + } +} - let s: &str = match msg { - SendStrOwned(ref s) => { - let slc: &str = *s; - slc - }, - SendStrStatic(s) => s, - }; - - // Truncate the string - let buf_bytes = 2048; - if s.len() > buf_bytes { - let s = s.slice(0, buf_bytes) + "[...]"; - print(s); - } else { - print(s) - }; - - fn print(s: &str) { - let dbg = STDERR_FILENO as ::io::fd_t; - dbg.write_str(s); - dbg.write_str("\n"); - dbg.flush(); - } +impl rt::io::Writer for StdErrLogger { + fn write(&mut self, buf: &[u8]) { + // Nothing like swapping between I/O implementations! In theory this + // could use the libuv bindings for writing to file descriptors, but + // that may not necessarily be desirable because logging should work + // outside of the uv loop. (modify with caution) + use io::Writer; + let dbg = ::libc::STDERR_FILENO as ::io::fd_t; + dbg.write(buf); } + + fn flush(&mut self) {} } + /// Configure logging by traversing the crate map and setting the /// per-module global logging flags based on the logging spec pub fn init() { diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 5c1bac7418e..b06385cbcf4 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -224,4 +224,5 @@ mod std { pub use os; pub use fmt; pub use to_bytes; + pub use logging; } diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index c315c3f9dfc..c38f3525867 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -125,14 +125,41 @@ impl FailWithCause for &'static str { } } -// FIXME #4427: Temporary until rt::rt_fail_ goes away +// This stage0 version is incredibly wrong. +#[cfg(stage0)] pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { use option::{Some, None}; use rt::in_green_task_context; use rt::task::Task; use rt::local::Local; use rt::logging::Logger; - use send_str::SendStrOwned; + use str::Str; + + unsafe { + let msg = str::raw::from_c_str(msg); + let file = str::raw::from_c_str(file); + if in_green_task_context() { + rterrln!("task failed at '%s', %s:%i", msg, file, line as int); + } else { + rterrln!("failed in non-task context at '%s', %s:%i", + msg, file, line as int); + } + + let task: *mut Task = Local::unsafe_borrow(); + if (*task).unwinder.unwinding { + rtabort!("unwinding again"); + } + (*task).unwinder.begin_unwind(); + } +} + +// FIXME #4427: Temporary until rt::rt_fail_ goes away +#[cfg(not(stage0))] +pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { + use rt::in_green_task_context; + use rt::task::Task; + use rt::local::Local; + use rt::logging::Logger; use str::Str; unsafe { @@ -140,22 +167,14 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { let msg = str::raw::from_c_str(msg); let file = str::raw::from_c_str(file); - // XXX: Logging doesn't work correctly in non-task context because it - // invokes the local heap if in_green_task_context() { - // XXX: Logging doesn't work here - the check to call the log - // function never passes - so calling the log function directly. + // Be careful not to allocate in this block, if we're failing we may + // have been failing due to a lack of memory in the first place... do Local::borrow |task: &mut Task| { - let msg = match task.name { - Some(ref name) => - fmt!("task '%s' failed at '%s', %s:%i", - name.as_slice(), msg, file, line as int), - None => - fmt!("task <unnamed> failed at '%s', %s:%i", - msg, file, line as int) - }; - - task.logger.log(SendStrOwned(msg)); + let n = task.name.map(|n| n.as_slice()).unwrap_or("<unnamed>"); + format_args!(|args| { task.logger.log(args) }, + "task '{}' failed at '{}', {}:{}", + n, msg.as_slice(), file.as_slice(), line); } } else { rterrln!("failed in non-task context at '%s', %s:%i", |
