diff options
| author | bors <bors@rust-lang.org> | 2013-08-27 11:35:51 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-08-27 11:35:51 -0700 |
| commit | c822d1070ac39871165df30ac8d09e733a6e7fb9 (patch) | |
| tree | 10a9f4f2282ba97a33ecde8d45984183608fafb6 /src/libstd | |
| parent | 7841b77676662ed657da7b8911dd0989ac743ca0 (diff) | |
| parent | cc59d9609740bd325a796ba0831af15b87f502ed (diff) | |
| download | rust-c822d1070ac39871165df30ac8d09e733a6e7fb9.tar.gz rust-c822d1070ac39871165df30ac8d09e733a6e7fb9.zip | |
auto merge of #8581 : FlaPer87/rust/issue/8232, r=bblum
As for now, rekillable is an unsafe function, instead, it should behave just like unkillable by encapsulating unsafe code within an unsafe block. This patch does that and removes unsafe blocks that were encapsulating rekillable calls throughout rust's libs. Fixes #8232
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/rt/kill.rs | 6 | ||||
| -rw-r--r-- | src/libstd/task/mod.rs | 81 |
2 files changed, 68 insertions, 19 deletions
diff --git a/src/libstd/rt/kill.rs b/src/libstd/rt/kill.rs index b0b425e3aee..94df621ce76 100644 --- a/src/libstd/rt/kill.rs +++ b/src/libstd/rt/kill.rs @@ -647,7 +647,11 @@ impl Death { /// All calls must be paired with a preceding call to inhibit_kill. #[inline] pub fn allow_kill(&mut self, already_failing: bool) { - rtassert!(self.unkillable != 0); + if self.unkillable == 0 { + // we need to decrement the counter before failing. + self.unkillable -= 1; + fail!("Cannot enter a rekillable() block without a surrounding unkillable()"); + } self.unkillable -= 1; if self.unkillable == 0 { rtassert!(self.kill_handle.is_some()); diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index e76b81a904d..f872c2614b9 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -597,21 +597,36 @@ pub fn unkillable<U>(f: &fn() -> U) -> U { } } -/// The inverse of unkillable. Only ever to be used nested in unkillable(). -pub unsafe fn rekillable<U>(f: &fn() -> U) -> U { +/** + * Makes killable a task marked as unkillable. This + * is meant to be used only nested in unkillable. + * + * # Example + * + * ~~~ + * do task::unkillable { + * do task::rekillable { + * // Task is killable + * } + * // Task is unkillable again + * } + */ +pub fn rekillable<U>(f: &fn() -> U) -> U { use rt::task::Task; - if in_green_task_context() { - let t = Local::unsafe_borrow::<Task>(); - do (|| { - (*t).death.allow_kill((*t).unwinder.unwinding); + unsafe { + if in_green_task_context() { + let t = Local::unsafe_borrow::<Task>(); + do (|| { + (*t).death.allow_kill((*t).unwinder.unwinding); + f() + }).finally { + (*t).death.inhibit_kill((*t).unwinder.unwinding); + } + } else { + // FIXME(#3095): As in unkillable(). f() - }).finally { - (*t).death.inhibit_kill((*t).unwinder.unwinding); } - } else { - // FIXME(#3095): As in unkillable(). - f() } } @@ -636,8 +651,8 @@ fn test_kill_unkillable_task() { } } -#[ignore(reason = "linked failure")] #[test] +#[ignore(cfg(windows))] fn test_kill_rekillable_task() { use rt::test::*; @@ -646,11 +661,9 @@ fn test_kill_rekillable_task() { do run_in_newsched_task { do task::try { do task::unkillable { - unsafe { - do task::rekillable { - do task::spawn { - fail!(); - } + do task::rekillable { + do task::spawn { + fail!(); } } } @@ -658,7 +671,39 @@ fn test_kill_rekillable_task() { } } -#[test] #[should_fail] +#[test] +#[should_fail] +#[ignore(cfg(windows))] +fn test_rekillable_not_nested() { + do rekillable { + // This should fail before + // receiving anything since + // this block should be nested + // into a unkillable block. + deschedule(); + } +} + + +#[test] +#[ignore(cfg(windows))] +fn test_rekillable_nested_failure() { + + let result = do task::try { + do unkillable { + do rekillable { + let (port,chan) = comm::stream(); + do task::spawn { chan.send(()); fail!(); } + port.recv(); // wait for child to exist + port.recv(); // block forever, expect to get killed. + } + } + }; + assert!(result.is_err()); +} + + +#[test] #[should_fail] #[ignore(cfg(windows))] fn test_cant_dup_task_builder() { let mut builder = task(); builder.unlinked(); |
