X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibstd%2Frt%2Ftask.rs;h=b4ead4252ca4158a461da8d94dea3b36a10f82bc;hb=f78293c274be2a23889f20942d75e9e45352a336;hp=583a1e0657cf86bd128b89299aa90a38e67c79a7;hpb=3f11f8738201dcf230a1647e30c312c980513b37;p=rust.git diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 583a1e0657c..b4ead4252ca 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -17,9 +17,11 @@ use borrow; use cast; use cleanup; +use clone::Clone; 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 +31,6 @@ 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; @@ -38,9 +39,6 @@ use task::{TaskResult, TaskOpts}; use unstable::finally::Finally; -#[cfg(stage0)] -pub use rt::unwind::begin_unwind; - // The Task struct represents all state associated with a rust // task. There are at this point two primary "subtypes" of task, // however instead of using a subtype we just have a "task_type" field @@ -58,8 +56,9 @@ pub struct Task { // Dynamic borrowck debugging info borrow_list: Option<~[BorrowRecord]>, - logger: Option, - stdout_handle: Option<~Writer>, + logger: Option<~Logger>, + stdout: Option<~Writer>, + stderr: Option<~Writer>, priv imp: Option<~Runtime>, } @@ -97,7 +96,8 @@ pub fn new() -> Task { name: None, borrow_list: None, logger: None, - stdout_handle: None, + stdout: None, + stderr: None, imp: None, } } @@ -126,13 +126,21 @@ pub fn run(~self, f: ||) -> ~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::); + 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. @@ -153,23 +161,23 @@ fn flush(w: Option<~Writer>) { // annihilated invoke TLS. Sadly these two operations seemed to // be intertwined, and miraculously work for now... let mut task = Local::borrow(None::); - let storage = task.get().storage.take(); + let storage_map = { + let task = task.get(); + let LocalStorage(ref mut optmap) = task.storage; + optmap.take() + }; drop(task); - drop(storage); + drop(storage_map); // 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::); - 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(); }) }; @@ -277,6 +285,13 @@ pub fn maybe_yield(mut ~self) { pub fn local_io<'a>(&'a mut self) -> Option> { self.imp.get_mut_ref().local_io() } + + /// Returns the stack bounds for this task in (lo, hi) format. The stack + /// bounds may not be known for all tasks, so the return value may be + /// `None`. + pub fn stack_bounds(&self) -> (uint, uint) { + self.imp.get_ref().stack_bounds() + } } impl Drop for Task { @@ -444,16 +459,20 @@ fn comm_shared_chan() { #[test] fn heap_cycles() { + use cell::RefCell; use option::{Option, Some, None}; struct List { - next: Option<@mut List>, + next: Option<@RefCell>, } - let a = @mut List { next: None }; - let b = @mut List { next: Some(a) }; + let a = @RefCell::new(List { next: None }); + let b = @RefCell::new(List { next: Some(a) }); - a.next = Some(b); + { + let mut a = a.borrow_mut(); + a.get().next = Some(b); + } } #[test]