about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-08-28 01:33:48 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-09-25 16:30:05 -0700
commiteb2b25dd6d38157213742b048fad63fa4ceec691 (patch)
treee41f9af78454e8f6641dead395274419d843ab63
parentaf25f58ac3da45899ed65b3af965150c8a90dcda (diff)
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.
-rw-r--r--src/libstd/logging.rs25
-rw-r--r--src/libstd/rt/logging.rs53
-rw-r--r--src/libstd/std.rs1
-rw-r--r--src/libstd/sys.rs51
-rw-r--r--src/libsyntax/ext/expand.rs12
-rw-r--r--src/test/compile-fail/issue-2823.rs3
-rw-r--r--src/test/run-fail/rt-log-trunc.rs74
7 files changed, 82 insertions, 137 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",
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 64f30803ca7..80cb9424fa1 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -813,13 +813,17 @@ pub fn std_macros() -> @str {
         ($lvl:expr, $arg:expr) => ({
             let lvl = $lvl;
             if lvl <= __log_level() {
-                ::std::logging::log(lvl, fmt!(\"%?\", $arg))
+                format_args!(|args| {
+                    ::std::logging::log(lvl, args)
+                }, \"{}\", fmt!(\"%?\", $arg))
             }
         });
         ($lvl:expr, $($arg:expr),+) => ({
             let lvl = $lvl;
             if lvl <= __log_level() {
-                ::std::logging::log(lvl, fmt!($($arg),+))
+                format_args!(|args| {
+                    ::std::logging::log(lvl, args)
+                }, \"{}\", fmt!($($arg),+))
             }
         })
     )
@@ -834,7 +838,9 @@ pub fn std_macros() -> @str {
         ($lvl:expr, $($arg:tt)+) => ({
             let lvl = $lvl;
             if lvl <= __log_level() {
-                ::std::logging::log(lvl, format!($($arg)+))
+                format_args!(|args| {
+                    ::std::logging::log(lvl, args)
+                }, $($arg)+)
             }
         })
     )
diff --git a/src/test/compile-fail/issue-2823.rs b/src/test/compile-fail/issue-2823.rs
index bf00dc139d0..58b216e8d11 100644
--- a/src/test/compile-fail/issue-2823.rs
+++ b/src/test/compile-fail/issue-2823.rs
@@ -20,6 +20,5 @@ impl Drop for C {
 
 fn main() {
     let c = C{ x: 2};
-    let d = c.clone(); //~ ERROR does not implement any method in scope
-    error!("%?", d.x);
+    let _d = c.clone(); //~ ERROR does not implement any method in scope
 }
diff --git a/src/test/run-fail/rt-log-trunc.rs b/src/test/run-fail/rt-log-trunc.rs
deleted file mode 100644
index 1dd27d7d3ae..00000000000
--- a/src/test/run-fail/rt-log-trunc.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2012 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.
-
-// Test that logs add `[...]` to truncated lines
-// error-pattern:[...]
-
-fn main() {
-    fail!("\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
-          ");
-}