about summary refs log tree commit diff
path: root/src/libstd/sys.rs
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 /src/libstd/sys.rs
parentaf25f58ac3da45899ed65b3af965150c8a90dcda (diff)
downloadrust-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/sys.rs')
-rw-r--r--src/libstd/sys.rs51
1 files changed, 35 insertions, 16 deletions
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",