about summary refs log tree commit diff
path: root/src/libstd/rt/task.rs
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-01-06 10:26:11 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-01-06 13:19:53 -0800
commitac2a24ecc9df66279a7b6df478593b34e1d2449f (patch)
tree06d4a206f68b583c558cc1eaf34b825f3539e6d5 /src/libstd/rt/task.rs
parenta6d3e57dca68fde4effdda3e4ae2887aa535fcd6 (diff)
downloadrust-ac2a24ecc9df66279a7b6df478593b34e1d2449f.tar.gz
rust-ac2a24ecc9df66279a7b6df478593b34e1d2449f.zip
Support arbitrary stdout/stderr/logger handles
This will allow capturing of common things like logging messages, stdout prints
(using stdio println), and failure messages (printed to stderr).  Any new prints
added to libstd should be funneled through these task handles to allow capture
as well.

Additionally, this commit redirects logging back through a `Logger` trait so the
log level can be usefully consumed by an arbitrary logger.

This commit also introduces methods to set the task-local stdout handles:

* std::io::stdio::set_stdout
* std::io::stdio::set_stderr
* std::io::logging::set_logger

These methods all return the previous logger just in case it needs to be used
for inspection.

I plan on using this infrastructure for extra::test soon, but we don't quite
have the primitives that I'd like to use for it, so it doesn't migrate
extra::test at this time.

Closes #6369
Diffstat (limited to 'src/libstd/rt/task.rs')
-rw-r--r--src/libstd/rt/task.rs44
1 files changed, 25 insertions, 19 deletions
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 3efa979e515..56fab6fe499 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -20,6 +20,7 @@ use cleanup;
 use io::Writer;
 use iter::{Iterator, Take};
 use local_data;
+use logging::Logger;
 use ops::Drop;
 use option::{Option, Some, None};
 use prelude::drop;
@@ -29,7 +30,6 @@ use rt::borrowck::BorrowRecord;
 use rt::borrowck;
 use rt::local::Local;
 use rt::local_heap::LocalHeap;
-use rt::logging::StdErrLogger;
 use rt::rtio::LocalIo;
 use rt::unwind::Unwinder;
 use send_str::SendStr;
@@ -58,8 +58,9 @@ pub struct Task {
     // Dynamic borrowck debugging info
     borrow_list: Option<~[BorrowRecord]>,
 
-    logger: Option<StdErrLogger>,
-    stdout_handle: Option<~Writer>,
+    logger: Option<~Logger>,
+    stdout: Option<~Writer>,
+    stderr: Option<~Writer>,
 
     priv imp: Option<~Runtime>,
 }
@@ -97,7 +98,8 @@ impl Task {
             name: None,
             borrow_list: None,
             logger: None,
-            stdout_handle: None,
+            stdout: None,
+            stderr: None,
             imp: None,
         }
     }
@@ -126,13 +128,21 @@ impl Task {
 
             // Run the task main function, then do some cleanup.
             f.finally(|| {
-                fn flush(w: Option<~Writer>) {
-                    match w {
-                        Some(mut w) => { w.flush(); }
-                        None => {}
-                    }
+                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 => {} }
                 }
 
+                // First, flush/destroy the user stdout/logger because these
+                // destructors can run arbitrary code.
+                close_outputs();
+
                 // First, destroy task-local storage. This may run user dtors.
                 //
                 // FIXME #8302: Dear diary. I'm so tired and confused.
@@ -164,16 +174,12 @@ impl Task {
                 // Destroy remaining boxes. Also may run user dtors.
                 unsafe { cleanup::annihilate(); }
 
-                // Finally flush and destroy any output handles which the task
-                // owns. There are no boxes here, and no user destructors should
-                // run after this any more.
-                let mut task = Local::borrow(None::<Task>);
-                let stdout = task.get().stdout_handle.take();
-                let logger = task.get().logger.take();
-                drop(task);
-
-                flush(stdout);
-                drop(logger);
+                // Finally, just in case user dtors printed/logged during TLS
+                // cleanup and annihilation, re-destroy stdout and the logger.
+                // Note that these will have been initialized with a
+                // runtime-provided type which we have control over what the
+                // destructor does.
+                close_outputs();
             })
         };