about summary refs log tree commit diff
path: root/src/libstd/task
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-08-02 16:06:13 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-08-02 17:31:45 -0400
commitd30cca46e61f8e5e604a87f0e623cb852be6c85f (patch)
treee42f180c70df6dc196d91c1e85f6324f470fa4b4 /src/libstd/task
parentcde6ad39920ddadd7c70921232ae92adff258367 (diff)
downloadrust-d30cca46e61f8e5e604a87f0e623cb852be6c85f.tar.gz
rust-d30cca46e61f8e5e604a87f0e623cb852be6c85f.zip
Fix embarrassing bug where 'unkillable' would unwind improperly when it receives a kill signal.
Diffstat (limited to 'src/libstd/task')
-rw-r--r--src/libstd/task/mod.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 19acedb56dd..e08297a1425 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -655,6 +655,47 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
     }
 }
 
+#[test] #[ignore(cfg(windows))]
+fn test_kill_unkillable_task() {
+    use rt::test::*;
+
+    // Attempt to test that when a kill signal is received at the start of an
+    // unkillable section, 'unkillable' unwinds correctly. This is actually
+    // quite a difficult race to expose, as the kill has to happen on a second
+    // CPU, *after* the spawner is already switched-back-to (and passes the
+    // killed check at the start of its timeslice). As far as I know, it's not
+    // possible to make this race deterministic, or even more likely to happen.
+    do run_in_newsched_task {
+        do task::try {
+            do task::spawn {
+                fail!();
+            }
+            do task::unkillable { }
+        };
+    }
+}
+
+#[test] #[ignore(cfg(windows))]
+fn test_kill_rekillable_task() {
+    use rt::test::*;
+
+    // Tests that when a kill signal is received, 'rekillable' and
+    // 'unkillable' unwind correctly in conjunction with each other.
+    do run_in_newsched_task {
+        do task::try {
+            do task::unkillable {
+                unsafe {
+                    do task::rekillable {
+                        do task::spawn {
+                            fail!();
+                        }
+                    }
+                }
+            }
+        };
+    }
+}
+
 #[test] #[should_fail] #[ignore(cfg(windows))]
 fn test_cant_dup_task_builder() {
     let mut builder = task();