The implementation currently contains a race that leads to segfaults.
All tasks are, by default, _linked_ to each other. That means that the fates
of all tasks are intertwined: if one fails, so do all the others.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task::spawn;
# use std::task;
# fn do_some_work() { loop { task::yield() } }
field (representing a successful result) or an `Err` result (representing
termination with an error).
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# fn some_condition() -> bool { false }
# fn calculate_result() -> int { 0 }
By default, task failure is _bidirectionally linked_, which means that if
either task fails, it kills the other one.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# use std::comm::oneshot;
# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }
internally, with additional logic to wait for the child task to finish
before returning. Hence:
-~~~
+~~~{.xfail-test .linked-failure}
# use std::comm::{stream, Chan, Port};
# use std::comm::oneshot;
# use std::task::{spawn, try};
Supervised task failure propagates across multiple generations even if
an intermediate generation has already exited:
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# use std::comm::oneshot;
# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }
Finally, tasks can be configured to not propagate failure to each
other at all, using `task::spawn_unlinked` for _isolated failure_.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# fn random() -> uint { 100 }
# fn sleep_for(i: uint) { for _ in range(0, i) { task::yield() } }
the string in response. The child terminates when it receives `0`.
Here is the function that implements the child task:
-~~~~
+~~~{.xfail-test .linked-failure}
# use extra::comm::DuplexStream;
# use std::uint;
fn stringifier(channel: &DuplexStream<~str, uint>) {
Here is the code for the parent task:
-~~~~
+~~~{.xfail-test .linked-failure}
# use std::task::spawn;
# use std::uint;
# use extra::comm::DuplexStream;
}
}
}
+
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_arc_condvar_poison() {
unsafe {
// child task must have finished by the time try returns
do m.lock { }
}
+ #[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_mutex_killed_cond() {
// Getting killed during cond wait must not corrupt the mutex while
assert!(!woken);
}
}
+ #[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_mutex_killed_broadcast() {
use std::unstable::finally::Finally;
// Test cases don't care about the spare killed flag.
fn make_kill_handle() -> KillHandle { let (h,_) = KillHandle::new(); h }
+ #[ignore(reason = "linked failure")]
#[test]
fn no_tombstone_success() {
do run_in_newsched_task {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_and_get_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_already_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_unkillably_and_get_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_on_pipe() {
// Tests the "killable" path of casting to/from uint.
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_unkillably_on_pipe() {
// Tests the "indestructible" path of casting to/from uint.
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_kill_unkillable_task() {
use rt::test::*;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_kill_rekillable_task() {
use rt::test::*;
#[cfg(test)]
fn block_forever() { let (po, _ch) = stream::<()>(); po.recv(); }
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port
use rt::test::run_in_newsched_task;
po.recv();
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails
use rt::test::run_in_newsched_task;
do spawn_unlinked { fail!(); }
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails
use rt::test::run_in_newsched_task;
do 16.times { task::yield(); }
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_sup_fail_down() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_fail_down() { // parent fails; child fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_default_opts() { // parent fails; child fails
use rt::test::run_in_newsched_task;
// A couple bonus linked failure tests - testing for failure propagation even
// when the middle task exits successfully early before kill signals are sent.
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_grandchild() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_secondborn() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_nephew_or_niece() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_propagate_sibling() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test]
#[ignore(cfg(windows))]
#[should_fail]
po.recv();
}
+#[ignore(reason = "linked failure")]
#[test]
#[ignore(cfg(windows))]
#[should_fail]
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_watched() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_indestructible() {
use rt::test::run_in_newsched_task;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:explicit failure
// Testing that runtime failure doesn't cause callbacks to abort abnormally.
// Instead the failure will be delivered after the callbacks return.
// except according to those terms.
+// xfail-test linked failure
// error-pattern:1 == 2
extern mod extra;
// except according to those terms.
+// xfail-test linked failure
// error-pattern:fail
use std::comm;
// except according to those terms.
+// xfail-test linked failure
// error-pattern:fail
use std::comm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:1 == 2
use std::comm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// error-pattern:explicit
extern mod extra;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:goodfail
use std::comm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-fast
// xfail-win32 #7999
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32 leaks
extern mod extra;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
extern mod extra;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// A port of task-killjoin to use a class with a dtor to manage
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// Create a task that is supervised by another task, join the supervised task