about summary refs log tree commit diff
path: root/src/liblog/lib.rs
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-01 10:19:42 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-03-20 10:56:27 -0700
commit1cc9718fdef63476ffdf3f0bcd74b554b083f378 (patch)
tree9ab128b25b8bd688a26897a5b8029672d737140e /src/liblog/lib.rs
parent46f649c479ce40f3b4590590dda6c2895e8d60f6 (diff)
downloadrust-1cc9718fdef63476ffdf3f0bcd74b554b083f378.tar.gz
rust-1cc9718fdef63476ffdf3f0bcd74b554b083f378.zip
Revert "Revert "std: Re-enable at_exit()""
This reverts commit aec67c2ee0f673ea7b0e21c2fe7e0f26a523d823.
Diffstat (limited to 'src/liblog/lib.rs')
-rw-r--r--src/liblog/lib.rs40
1 files changed, 28 insertions, 12 deletions
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index c634a46888e..4537fc763c9 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -183,10 +183,9 @@ use std::io::{self, Stderr};
 use std::io::prelude::*;
 use std::mem;
 use std::env;
-use std::ptr;
 use std::rt;
 use std::slice;
-use std::sync::{Once, ONCE_INIT};
+use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
 
 use directive::LOG_LEVEL_NAMES;
 
@@ -202,6 +201,8 @@ pub const MAX_LOG_LEVEL: u32 = 255;
 /// The default logging level of a crate if no other is specified.
 const DEFAULT_LOG_LEVEL: u32 = 1;
 
+static LOCK: StaticMutex = MUTEX_INIT;
+
 /// An unsafe constant that is the maximum logging level of any module
 /// specified. This is the first line of defense to determining whether a
 /// logging statement should be run.
@@ -286,9 +287,18 @@ impl Drop for DefaultLogger {
 pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
     // Test the literal string from args against the current filter, if there
     // is one.
-    match unsafe { FILTER.as_ref() } {
-        Some(filter) if !args.to_string().contains(&filter[..]) => return,
-        _ => {}
+    unsafe {
+        let _g = LOCK.lock();
+        match FILTER as uint {
+            0 => {}
+            1 => panic!("cannot log after main thread has exited"),
+            n => {
+                let filter = mem::transmute::<_, &String>(n);
+                if !args.to_string().contains(&filter[..]) {
+                    return
+                }
+            }
+        }
     }
 
     // Completely remove the local logger from TLS in case anyone attempts to
@@ -370,9 +380,15 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
 
     // This assertion should never get tripped unless we're in an at_exit
     // handler after logging has been torn down and a logging attempt was made.
-    assert!(unsafe { !DIRECTIVES.is_null() });
 
-    enabled(level, module, unsafe { (*DIRECTIVES).iter() })
+    let _g = LOCK.lock();
+    unsafe {
+        assert!(DIRECTIVES as uint != 0);
+        assert!(DIRECTIVES as uint != 1,
+                "cannot log after the main thread has exited");
+
+        enabled(level, module, (*DIRECTIVES).iter())
+    }
 }
 
 fn enabled(level: u32,
@@ -428,14 +444,14 @@ fn init() {
 
         // Schedule the cleanup for the globals for when the runtime exits.
         rt::at_exit(move || {
+            let _g = LOCK.lock();
             assert!(!DIRECTIVES.is_null());
-            let _directives: Box<Vec<directive::LogDirective>> =
-                Box::from_raw(DIRECTIVES);
-            DIRECTIVES = ptr::null_mut();
+            let _directives = Box::from_raw(DIRECTIVES);
+            DIRECTIVES = 1 as *mut _;
 
             if !FILTER.is_null() {
-                let _filter: Box<String> = Box::from_raw(FILTER);
-                FILTER = 0 as *mut _;
+                let _filter = Box::from_raw(FILTER);
+                FILTER = 1 as *mut _;
             }
         });
     }