]> git.lizzy.rs Git - rust.git/commitdiff
Don't abort if the runtime is run twice.
authorAlex Crichton <alex@alexcrichton.com>
Sun, 6 Oct 2013 04:58:55 +0000 (21:58 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 9 Oct 2013 19:38:18 +0000 (12:38 -0700)
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

src/libstd/macros.rs
src/libstd/rt/mod.rs
src/test/run-pass/rt-run-twice.rs [new file with mode: 0644]

index 0b1475ff3801420b5526bda14833ce1185b873d4..2ef25548535dc4b8444efcb3f742706aa5309b8c 100644 (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);
-    }
-}
index 2ece2800cf267ad21f2f0608fde79082f491ec6d..fa9d767ec3fc9b5350243382dd3ad8facea738b3 100644 (file)
@@ -70,7 +70,7 @@
 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 (file)
index 0000000..0bb02ed
--- /dev/null
@@ -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
+}