Skip to content

Commit 11d5670

Browse files
committed
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
2 parents 62812f1 + 8fcf62b commit 11d5670

File tree

3 files changed

+34
-40
lines changed

3 files changed

+34
-40
lines changed

src/libstd/macros.rs

-38
Original file line numberDiff line numberDiff line change
@@ -42,41 +42,3 @@ macro_rules! rtabort(
4242
::rt::util::abort(format!($($msg)*));
4343
} )
4444
)
45-
46-
macro_rules! assert_once_ever(
47-
($($msg:tt)+) => ( {
48-
// FIXME(#8472) extra function should not be needed to hide unsafe
49-
fn assert_once_ever() {
50-
unsafe {
51-
static mut already_happened: int = 0;
52-
// Double-check lock to avoid a swap in the common case.
53-
if already_happened != 0 ||
54-
::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
55-
fail2!("assert_once_ever happened twice: {}",
56-
format!($($msg)+));
57-
}
58-
}
59-
}
60-
assert_once_ever();
61-
} )
62-
)
63-
64-
#[cfg(test)]
65-
mod tests {
66-
#[test]
67-
fn test_assert_once_ever_ok() {
68-
assert_once_ever!("help i'm stuck in an");
69-
assert_once_ever!("assertion error message");
70-
}
71-
72-
#[test] #[ignore(cfg(windows))] #[should_fail]
73-
fn test_assert_once_ever_fail() {
74-
use task;
75-
76-
fn f() { assert_once_ever!("if you're seeing this... good!") }
77-
78-
// linked & watched, naturally
79-
task::spawn(f);
80-
task::spawn(f);
81-
}
82-
}

src/libstd/rt/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use rt::sched::{Scheduler, Shutdown};
6868
use rt::sleeper_list::SleeperList;
6969
use rt::task::{Task, SchedTask, GreenTask, Sched};
7070
use rt::uv::uvio::UvEventLoop;
71-
use unstable::atomics::{AtomicInt, SeqCst};
71+
use unstable::atomics::{AtomicInt, AtomicBool, SeqCst};
7272
use unstable::sync::UnsafeArc;
7373
use vec;
7474
use vec::{OwnedVector, MutableVector, ImmutableVector};
@@ -311,11 +311,17 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
311311
let exit_code = UnsafeArc::new(AtomicInt::new(0));
312312
let exit_code_clone = exit_code.clone();
313313

314+
// Used to sanity check that the runtime only exits once
315+
let exited_already = UnsafeArc::new(AtomicBool::new(false));
316+
314317
// When the main task exits, after all the tasks in the main
315318
// task tree, shut down the schedulers and set the exit code.
316319
let handles = Cell::new(handles);
317320
let on_exit: ~fn(bool) = |exit_success| {
318-
assert_once_ever!("last task exiting");
321+
unsafe {
322+
assert!(!(*exited_already.get()).swap(true, SeqCst),
323+
"the runtime already exited");
324+
}
319325

320326
let mut handles = handles.take();
321327
for handle in handles.mut_iter() {

src/test/run-pass/rt-run-twice.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast windows uses a different test runner
12+
13+
use std::rt;
14+
15+
#[start]
16+
fn start(argc: int, argv: **u8) -> int {
17+
do rt::start(argc, argv) {
18+
println("First invocation");
19+
};
20+
21+
do rt::start(argc, argv) {
22+
println("Second invocation");
23+
};
24+
25+
0
26+
}

0 commit comments

Comments
 (0)