Make at_exit initialize lazily
This commit is contained in:
parent
b66681cd31
commit
c009bfdf94
@ -138,7 +138,7 @@ pub use funcs::c95::stdio::{fread, freopen, fseek, fsetpos, ftell};
|
||||
pub use funcs::c95::stdio::{fwrite, perror, puts, remove, rename, rewind};
|
||||
pub use funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc};
|
||||
|
||||
pub use funcs::c95::stdlib::{abs, atof, atoi, calloc, exit, _exit};
|
||||
pub use funcs::c95::stdlib::{abs, atof, atoi, calloc, exit, _exit, atexit};
|
||||
pub use funcs::c95::stdlib::{free, getenv, labs, malloc, rand};
|
||||
pub use funcs::c95::stdlib::{realloc, srand, strtod, strtol};
|
||||
pub use funcs::c95::stdlib::{strtoul, system};
|
||||
@ -4102,7 +4102,7 @@ pub mod funcs {
|
||||
pub fn free(p: *mut c_void);
|
||||
pub fn exit(status: c_int) -> !;
|
||||
pub fn _exit(status: c_int) -> !;
|
||||
// Omitted: atexit.
|
||||
pub fn atexit(cb: extern fn()) -> c_int;
|
||||
pub fn system(s: *const c_char) -> c_int;
|
||||
pub fn getenv(s: *const c_char) -> *mut c_char;
|
||||
// Omitted: bsearch, qsort
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
QUEUE.store(mem::transmute(state), atomic::SeqCst);
|
||||
libc::atexit(run);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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...
|
||||
|
Loading…
x
Reference in New Issue
Block a user