]> git.lizzy.rs Git - rust.git/commitdiff
Make at_exit initialize lazily
authorAaron Turon <aturon@mozilla.com>
Tue, 25 Nov 2014 01:22:40 +0000 (17:22 -0800)
committerAaron Turon <aturon@mozilla.com>
Fri, 19 Dec 2014 07:31:34 +0000 (23:31 -0800)
src/liblibc/lib.rs
src/libstd/os.rs
src/libstd/rt/at_exit_imp.rs
src/libstd/rt/mod.rs

index 8825099e36c35b071d3b16a3deef0c19b78815db..6ab00cfe8fa6a616cd67b54deec98bb7013065ef 100644 (file)
 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 fn strtoul(s: *const c_char, endp: *mut *mut c_char,
                 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
index f46d9ab7c7e4bbf635926206232881b91035eeb4..550c8d2fabacaa1bc49a418e775e971ae377fab2 100644 (file)
@@ -43,7 +43,6 @@
 use ops::{Drop, FnOnce};
 use option::Option;
 use option::Option::{Some, None};
-use os;
 use path::{Path, GenericPath, BytesContainer};
 use sys;
 use ptr::RawPtr;
index 086079c312ad4c3dc6b471fd098dafbc188c4076..9ddb59bfffcf537771483faf687e6c9bf9864d16 100644 (file)
 
 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;
 
 
 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);
+    }
+}
index 21c8197ef05588f6468c68daa3cabacb77cdbc83..5d5ccefda5dc25acf689f97c4bfad7d42917156f 100644 (file)
@@ -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...