diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 0b1475ff38014..2ef25548535dc 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -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); - } -} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 2ece2800cf267..fa9d767ec3fc9 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -70,7 +70,7 @@ use rt::task::{Task, SchedTask, GreenTask, Sched}; use rt::thread::Thread; use rt::work_queue::WorkQueue; 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}; @@ -298,11 +298,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() { diff --git a/src/test/run-pass/rt-run-twice.rs b/src/test/run-pass/rt-run-twice.rs new file mode 100644 index 0000000000000..0bb02ed5498b7 --- /dev/null +++ b/src/test/run-pass/rt-run-twice.rs @@ -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 or the MIT license +// , 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 +}