about summary refs log tree commit diff
path: root/src/libstd/task/mod.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-02 14:55:54 -0700
committerbors <bors@rust-lang.org>2013-08-02 14:55:54 -0700
commit3ddc72f69be4d0a2027ff598ad262ea2b2ca3812 (patch)
tree5942120bc4dba4d4b2da56457b425145030daf29 /src/libstd/task/mod.rs
parentf1c1f92d0c555d6e38ad1cac55926d6d9c9b090f (diff)
parent43fecf3556b47305320221586f48f89fe2f6c505 (diff)
downloadrust-3ddc72f69be4d0a2027ff598ad262ea2b2ca3812.tar.gz
rust-3ddc72f69be4d0a2027ff598ad262ea2b2ca3812.zip
auto merge of #8234 : bblum/rust/assorted-fixes, r=brson
This fixes 4 bugs that prevented the extra::arc and extra::sync tests from passing on the new runtime.

* In ```Add SendDeferred trait``` I add a non-rescheduling ```send_deferred``` method to our various channel types. The ```extra::sync``` concurrency primitives need this guarantee so they can send while inside of an exclusive. (This fixes deterministic deadlocks seen with ```RUST_THREADS=1```.)
* In "Fix nasty double-free bug" I make sure that a ```ChanOne``` suppresses_finalize *before* rescheduling away to the receiver, so in case it gets a kill signal upon coming back, the destructor is inhibited as desired. (This is pretty uncommon on multiple CPUs but showed up always with ```RUST_THREADS=1```.)
* In ```Fix embarrassing bug where 'unkillable' would unwind improperly``` I make sure the task's unkillable counter stays consistent when a kill signal is received right at the start of an unkillable section. (This is a very uncommon race and can only occur with multiple CPUs.)
* In ```Don't fail from kill signals if already unwinding``` I do pretty much what it says on the tin. Surprising that it took the whole suite of sync/arc tests to expose this.

The other two commits are cleanup.

r @brson
Diffstat (limited to 'src/libstd/task/mod.rs')
-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();