diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-08-03 14:43:16 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-08-03 14:43:16 -0700 |
| commit | 3c9e39335431ca4bfe05d06735fed7d7edae9029 (patch) | |
| tree | 3bc72cddaa4108b794859bed3fe46960502a908c /src/libstd | |
| parent | 800dbffa698007abb5b4318538c8c2ffbd08010b (diff) | |
| download | rust-3c9e39335431ca4bfe05d06735fed7d7edae9029.tar.gz rust-3c9e39335431ca4bfe05d06735fed7d7edae9029.zip | |
std::rt: Run local storage cleanup and the box annihilator inside the try/catch
And before collect_failure. These are both running user dtors and need to be handled in the task try/catch block and before the final task cleanup code.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/rt/task.rs | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index b242ee13fa6..abafe1cf209 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -27,6 +27,7 @@ use super::local_heap::LocalHeap; use rt::sched::{Scheduler, SchedHandle}; use rt::stack::{StackSegment, StackPool}; use rt::context::Context; +use unstable::finally::Finally; use task::spawn::Taskgroup; use cell::Cell; @@ -211,40 +212,34 @@ impl Task { pub fn run(&mut self, f: &fn()) { rtdebug!("run called on task: %u", borrow::to_uint(self)); - self.unwinder.try(f); - // FIXME(#7544): We pass the taskgroup into death so that it can be - // dropped while the unkillable counter is set. This should not be - // necessary except for an extraneous clone() in task/spawn.rs that - // causes a killhandle to get dropped, which mustn't receive a kill - // signal since we're outside of the unwinder's try() scope. - // { let _ = self.taskgroup.take(); } - self.death.collect_failure(!self.unwinder.unwinding, self.taskgroup.take()); - self.destroy(); - } - /// must be called manually before finalization to clean up - /// thread-local resources. Some of the routines here expect - /// Task to be available recursively so this must be - /// called unsafely, without removing Task from - /// thread-local-storage. - fn destroy(&mut self) { + // The only try/catch block in the world. Attempt to run the task's + // client-specified code and catch any failures. + do self.unwinder.try { - rtdebug!("DESTROYING TASK: %u", borrow::to_uint(self)); + // Run the task main function, then do some cleanup. + do f.finally { - do Local::borrow::<Task, ()> |task| { - assert!(borrow::ref_eq(task, self)); - } + // Destroy task-local storage. This may run user dtors. + match self.storage { + LocalStorage(ptr, Some(ref dtor)) => { + (*dtor)(ptr) + } + _ => () + } - match self.storage { - LocalStorage(ptr, Some(ref dtor)) => { - (*dtor)(ptr) + // Destroy remaining boxes. Also may run user dtors. + unsafe { cleanup::annihilate(); } } - _ => () } - // Destroy remaining boxes - unsafe { cleanup::annihilate(); } - + // FIXME(#7544): We pass the taskgroup into death so that it can be + // dropped while the unkillable counter is set. This should not be + // necessary except for an extraneous clone() in task/spawn.rs that + // causes a killhandle to get dropped, which mustn't receive a kill + // signal since we're outside of the unwinder's try() scope. + // { let _ = self.taskgroup.take(); } + self.death.collect_failure(!self.unwinder.unwinding, self.taskgroup.take()); self.destroyed = true; } |
