about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-08-03 14:43:16 -0700
committerBrian Anderson <banderson@mozilla.com>2013-08-03 14:43:16 -0700
commit3c9e39335431ca4bfe05d06735fed7d7edae9029 (patch)
tree3bc72cddaa4108b794859bed3fe46960502a908c /src/libstd
parent800dbffa698007abb5b4318538c8c2ffbd08010b (diff)
downloadrust-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.rs49
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;
     }