diff options
| author | bors <bors@rust-lang.org> | 2013-08-01 18:01:42 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-08-01 18:01:42 -0700 |
| commit | 5890fcf87295d5b7a8f4ffa8d9918f755f72baf8 (patch) | |
| tree | 6bdd10dda4a962843c3dce5dee33e509152e95cb /src/libstd/task | |
| parent | d346f1a40e0d0ebe24e60d418f304641fc26f9b0 (diff) | |
| parent | ce761f4980e6cdc6115608e6db551bdf1c49387f (diff) | |
| download | rust-5890fcf87295d5b7a8f4ffa8d9918f755f72baf8.tar.gz rust-5890fcf87295d5b7a8f4ffa8d9918f755f72baf8.zip | |
auto merge of #8116 : toddaaro/rust/tls-tk-pr-pre, r=brson
Merged with task killing code this time around.
Diffstat (limited to 'src/libstd/task')
| -rw-r--r-- | src/libstd/task/mod.rs | 231 | ||||
| -rw-r--r-- | src/libstd/task/spawn.rs | 43 |
2 files changed, 165 insertions, 109 deletions
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index d0124407bd4..7a864ecb867 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -677,121 +677,190 @@ fn block_forever() { let (po, _ch) = stream::<()>(); po.recv(); } #[test] #[ignore(cfg(windows))] fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port - let (po, ch) = stream(); - let ch = SharedChan::new(ch); - do spawn_unlinked { - let ch = ch.clone(); + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let (po, ch) = stream(); + let ch = SharedChan::new(ch); do spawn_unlinked { - // Give middle task a chance to fail-but-not-kill-us. - do 16.times { task::yield(); } - ch.send(()); // If killed first, grandparent hangs. + let ch = ch.clone(); + do spawn_unlinked { + // Give middle task a chance to fail-but-not-kill-us. + do 16.times { task::yield(); } + ch.send(()); // If killed first, grandparent hangs. + } + fail!(); // Shouldn't kill either (grand)parent or (grand)child. } - fail!(); // Shouldn't kill either (grand)parent or (grand)child. + po.recv(); } - po.recv(); } #[test] #[ignore(cfg(windows))] fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails - do spawn_unlinked { fail!(); } + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + do spawn_unlinked { fail!(); } + } } #[test] #[ignore(cfg(windows))] fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails - do spawn_supervised { fail!(); } - // Give child a chance to fail-but-not-kill-us. - do 16.times { task::yield(); } + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + do spawn_supervised { fail!(); } + // Give child a chance to fail-but-not-kill-us. + do 16.times { task::yield(); } + } } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_unlinked_sup_fail_down() { - do spawn_supervised { block_forever(); } - fail!(); // Shouldn't leave a child hanging around. + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + do spawn_supervised { block_forever(); } + fail!(); // Shouldn't leave a child hanging around. + }; + assert!(result.is_err()); + } } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_sup_fail_up() { // child fails; parent fails - // Unidirectional "parenting" shouldn't override bidirectional linked. - // We have to cheat with opts - the interface doesn't support them because - // they don't make sense (redundant with task().supervised()). - let mut b0 = task(); - b0.opts.linked = true; - b0.opts.supervised = true; - - do b0.spawn { - fail!(); + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Unidirectional "parenting" shouldn't override bidirectional linked. + // We have to cheat with opts - the interface doesn't support them because + // they don't make sense (redundant with task().supervised()). + let mut b0 = task(); + b0.opts.linked = true; + b0.opts.supervised = true; + + do b0.spawn { + fail!(); + } + block_forever(); // We should get punted awake + }; + assert!(result.is_err()); } - block_forever(); // We should get punted awake } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_sup_fail_down() { // parent fails; child fails - // We have to cheat with opts - the interface doesn't support them because - // they don't make sense (redundant with task().supervised()). - let mut b0 = task(); - b0.opts.linked = true; - b0.opts.supervised = true; - do b0.spawn { block_forever(); } - fail!(); // *both* mechanisms would be wrong if this didn't kill the child + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // We have to cheat with opts - the interface doesn't support them because + // they don't make sense (redundant with task().supervised()). + let mut b0 = task(); + b0.opts.linked = true; + b0.opts.supervised = true; + do b0.spawn { block_forever(); } + fail!(); // *both* mechanisms would be wrong if this didn't kill the child + }; + assert!(result.is_err()); + } } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails - // Default options are to spawn linked & unsupervised. - do spawn { fail!(); } - block_forever(); // We should get punted awake + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Default options are to spawn linked & unsupervised. + do spawn { fail!(); } + block_forever(); // We should get punted awake + }; + assert!(result.is_err()); + } } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_unsup_fail_down() { // parent fails; child fails - // Default options are to spawn linked & unsupervised. - do spawn { block_forever(); } - fail!(); + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Default options are to spawn linked & unsupervised. + do spawn { block_forever(); } + fail!(); + }; + assert!(result.is_err()); + } } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_unsup_default_opts() { // parent fails; child fails - // Make sure the above test is the same as this one. - let mut builder = task(); - builder.linked(); - do builder.spawn { block_forever(); } - fail!(); + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Make sure the above test is the same as this one. + let mut builder = task(); + builder.linked(); + do builder.spawn { block_forever(); } + fail!(); + }; + assert!(result.is_err()); + } } // A couple bonus linked failure tests - testing for failure propagation even // when the middle task exits successfully early before kill signals are sent. -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_failure_propagate_grandchild() { - // Middle task exits; does grandparent's failure propagate across the gap? - do spawn_supervised { - do spawn_supervised { block_forever(); } + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Middle task exits; does grandparent's failure propagate across the gap? + do spawn_supervised { + do spawn_supervised { block_forever(); } + } + do 16.times { task::yield(); } + fail!(); + }; + assert!(result.is_err()); } - do 16.times { task::yield(); } - fail!(); } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_failure_propagate_secondborn() { - // First-born child exits; does parent's failure propagate to sibling? - do spawn_supervised { - do spawn { block_forever(); } // linked + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // First-born child exits; does parent's failure propagate to sibling? + do spawn_supervised { + do spawn { block_forever(); } // linked + } + do 16.times { task::yield(); } + fail!(); + }; + assert!(result.is_err()); } - do 16.times { task::yield(); } - fail!(); } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_failure_propagate_nephew_or_niece() { - // Our sibling exits; does our failure propagate to sibling's child? - do spawn { // linked - do spawn_supervised { block_forever(); } + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Our sibling exits; does our failure propagate to sibling's child? + do spawn { // linked + do spawn_supervised { block_forever(); } + } + do 16.times { task::yield(); } + fail!(); + }; + assert!(result.is_err()); } - do 16.times { task::yield(); } - fail!(); } -#[test] #[should_fail] #[ignore(cfg(windows))] +#[test] #[ignore(cfg(windows))] fn test_spawn_linked_sup_propagate_sibling() { - // Middle sibling exits - does eldest's failure propagate to youngest? - do spawn { // linked - do spawn { block_forever(); } // linked + use rt::test::run_in_newsched_task; + do run_in_newsched_task { + let result: Result<(),()> = do try { + // Middle sibling exits - does eldest's failure propagate to youngest? + do spawn { // linked + do spawn { block_forever(); } // linked + } + do 16.times { task::yield(); } + fail!(); + }; + assert!(result.is_err()); } - do 16.times { task::yield(); } - fail!(); } #[test] @@ -1149,11 +1218,15 @@ fn test_child_doesnt_ref_parent() { fn child_no(x: uint) -> ~fn() { return || { if x < generations { - task::spawn(child_no(x+1)); + let mut t = task(); + t.unwatched(); + t.spawn(child_no(x+1)); } } } - task::spawn(child_no(0)); + let mut t = task(); + t.unwatched(); + t.spawn(child_no(0)); } #[test] @@ -1167,9 +1240,9 @@ fn test_simple_newsched_spawn() { #[test] #[ignore(cfg(windows))] fn test_spawn_watched() { - use rt::test::{run_in_newsched_task, spawntask_try}; + use rt::test::run_in_newsched_task; do run_in_newsched_task { - let result = do spawntask_try { + let result = do try { let mut t = task(); t.unlinked(); t.watched(); @@ -1189,9 +1262,9 @@ fn test_spawn_watched() { #[test] #[ignore(cfg(windows))] fn test_indestructible() { - use rt::test::{run_in_newsched_task, spawntask_try}; + use rt::test::run_in_newsched_task; do run_in_newsched_task { - let result = do spawntask_try { + let result = do try { let mut t = task(); t.watched(); t.supervised(); diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 4558f8e32c1..88f214ef4c0 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -653,22 +653,16 @@ fn enlist_many(child: TaskHandle, child_arc: &TaskGroupArc, pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { match context() { - OldTaskContext => { - spawn_raw_oldsched(opts, f) - } - TaskContext => { - spawn_raw_newsched(opts, f) - } - SchedulerContext => { - fail!("can't spawn from scheduler context") - } - GlobalContext => { - fail!("can't spawn from global context") - } + OldTaskContext => spawn_raw_oldsched(opts, f), + TaskContext => spawn_raw_newsched(opts, f), + SchedulerContext => fail!("can't spawn from scheduler context"), + GlobalContext => fail!("can't spawn from global context"), } } fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { + use rt::sched::*; + let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised)); let indestructible = opts.indestructible; @@ -700,19 +694,11 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { } }; - let mut task = unsafe { - let sched = Local::unsafe_borrow::<Scheduler>(); - rtdebug!("unsafe borrowed sched"); - - if opts.watched { - let child_wrapper = Cell::new(child_wrapper); - do Local::borrow::<Task, ~Task>() |running_task| { - ~running_task.new_child(&mut (*sched).stack_pool, child_wrapper.take()) - } - } else { - // An unwatched task is a new root in the exit-code propagation tree - ~Task::new_root(&mut (*sched).stack_pool, child_wrapper) - } + let mut task = if opts.watched { + Task::build_child(child_wrapper) + } else { + // An unwatched task is a new root in the exit-code propagation tree + Task::build_root(child_wrapper) }; if opts.notify_chan.is_some() { @@ -727,12 +713,9 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { } task.name = opts.name.take(); + rtdebug!("spawn calling run_task"); + Scheduler::run_task(task); - rtdebug!("spawn about to take scheduler"); - - let sched = Local::take::<Scheduler>(); - rtdebug!("took sched in spawn"); - sched.schedule_task(task); } fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { |
