auto merge of #9742 : alexcrichton/rust/issue-9739, r=brson

This changes an `assert_once_ever!` assertion to just a plain old assertion
around an atomic boolean to ensure that one particular runtime doesn't attempt
to exit twice.

Closes #9739
This commit is contained in:
bors 2013-10-09 14:21:38 -07:00
commit 11d5670647
3 changed files with 34 additions and 40 deletions

View File

@ -42,41 +42,3 @@ macro_rules! rtabort(
::rt::util::abort(format!($($msg)*));
} )
)
macro_rules! assert_once_ever(
($($msg:tt)+) => ( {
// FIXME(#8472) extra function should not be needed to hide unsafe
fn assert_once_ever() {
unsafe {
static mut already_happened: int = 0;
// Double-check lock to avoid a swap in the common case.
if already_happened != 0 ||
::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
fail2!("assert_once_ever happened twice: {}",
format!($($msg)+));
}
}
}
assert_once_ever();
} )
)
#[cfg(test)]
mod tests {
#[test]
fn test_assert_once_ever_ok() {
assert_once_ever!("help i'm stuck in an");
assert_once_ever!("assertion error message");
}
#[test] #[ignore(cfg(windows))] #[should_fail]
fn test_assert_once_ever_fail() {
use task;
fn f() { assert_once_ever!("if you're seeing this... good!") }
// linked & watched, naturally
task::spawn(f);
task::spawn(f);
}
}

View File

@ -68,7 +68,7 @@
use rt::sleeper_list::SleeperList;
use rt::task::{Task, SchedTask, GreenTask, Sched};
use rt::uv::uvio::UvEventLoop;
use unstable::atomics::{AtomicInt, SeqCst};
use unstable::atomics::{AtomicInt, AtomicBool, SeqCst};
use unstable::sync::UnsafeArc;
use vec;
use vec::{OwnedVector, MutableVector, ImmutableVector};
@ -311,11 +311,17 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
let exit_code = UnsafeArc::new(AtomicInt::new(0));
let exit_code_clone = exit_code.clone();
// Used to sanity check that the runtime only exits once
let exited_already = UnsafeArc::new(AtomicBool::new(false));
// When the main task exits, after all the tasks in the main
// task tree, shut down the schedulers and set the exit code.
let handles = Cell::new(handles);
let on_exit: ~fn(bool) = |exit_success| {
assert_once_ever!("last task exiting");
unsafe {
assert!(!(*exited_already.get()).swap(true, SeqCst),
"the runtime already exited");
}
let mut handles = handles.take();
for handle in handles.mut_iter() {

View File

@ -0,0 +1,26 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-fast windows uses a different test runner
use std::rt;
#[start]
fn start(argc: int, argv: **u8) -> int {
do rt::start(argc, argv) {
println("First invocation");
};
do rt::start(argc, argv) {
println("Second invocation");
};
0
}