diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/os.rs | 1 | ||||
| -rw-r--r-- | src/libstd/rt/at_exit_imp.rs | 41 | ||||
| -rw-r--r-- | src/libstd/rt/mod.rs | 2 |
3 files changed, 23 insertions, 21 deletions
diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f46d9ab7c7e..550c8d2faba 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -43,7 +43,6 @@ use boxed::Box; use ops::{Drop, FnOnce}; use option::Option; use option::Option::{Some, None}; -use os; use path::{Path, GenericPath, BytesContainer}; use sys; use ptr::RawPtr; diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 086079c312a..9ddb59bfffc 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -14,9 +14,10 @@ use core::prelude::*; +use libc; use boxed::Box; use vec::Vec; -use sync::atomic; +use sync::{atomic, Once, ONCE_INIT}; use mem; use thunk::Thunk; @@ -24,31 +25,21 @@ use rt::exclusive::Exclusive; type Queue = Exclusive<Vec<Thunk>>; +static INIT: Once = ONCE_INIT; static QUEUE: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; static RUNNING: atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL; -pub fn init() { +fn init() { let state: Box<Queue> = box Exclusive::new(Vec::new()); unsafe { - rtassert!(!RUNNING.load(atomic::SeqCst)); - assert!(QUEUE.swap(mem::transmute(state), atomic::SeqCst) == 0); - } -} - -pub fn push(f: Thunk) { - unsafe { - // Note that the check against 0 for the queue pointer is not atomic at - // all with respect to `run`, meaning that this could theoretically be a - // use-after-free. There's not much we can do to protect against that, - // however. Let's just assume a well-behaved runtime and go from there! - rtassert!(!RUNNING.load(atomic::SeqCst)); - let queue = QUEUE.load(atomic::SeqCst); - rtassert!(queue != 0); - (*(queue as *const Queue)).lock().push(f); + QUEUE.store(mem::transmute(state), atomic::SeqCst); + libc::atexit(run); } } -pub fn run() { +// Note: this is private and so can only be called via atexit above, +// which guarantees initialization. +extern fn run() { let cur = unsafe { rtassert!(!RUNNING.load(atomic::SeqCst)); let queue = QUEUE.swap(0, atomic::SeqCst); @@ -63,3 +54,17 @@ pub fn run() { to_run.invoke(()); } } + +pub fn push(f: Thunk) { + INIT.doit(init); + unsafe { + // Note that the check against 0 for the queue pointer is not atomic at + // all with respect to `run`, meaning that this could theoretically be a + // use-after-free. There's not much we can do to protect against that, + // however. Let's just assume a well-behaved runtime and go from there! + rtassert!(!RUNNING.load(atomic::SeqCst)); + let queue = QUEUE.load(atomic::SeqCst); + rtassert!(queue != 0); + (*(queue as *const Queue)).lock().push(f); + } +} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 21c8197ef05..5d5ccefda5d 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -100,7 +100,6 @@ pub fn init(argc: int, argv: *const *const u8) { unsafe { args::init(argc, argv); local_ptr::init(); - at_exit_imp::init(); thread::init(); unwind::register(failure::on_fail); } @@ -212,7 +211,6 @@ pub unsafe fn cleanup() { args::cleanup(); thread::cleanup(); local_ptr::cleanup(); - at_exit_imp::run(); } // FIXME: these probably shouldn't be public... |
