about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/os.rs1
-rw-r--r--src/libstd/rt/at_exit_imp.rs41
-rw-r--r--src/libstd/rt/mod.rs2
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...