Selaa lähdekoodia

Logging symbols for shim

To allow custom logging target, we replace the direct libc symbols by an import from the shim crate, which can then be replace to match desired behavior.
ticki 8 vuotta sitten
vanhempi
commit
453db85480
6 muutettua tiedostoa jossa 39 lisäystä ja 29 poistoa
  1. 10 1
      shim/src/lib.rs
  2. 1 4
      src/bookkeeper.rs
  3. 2 1
      src/fail.rs
  4. 4 4
      src/log.rs
  5. 9 0
      src/sys.rs
  6. 13 19
      src/write.rs

+ 10 - 1
shim/src/lib.rs

@@ -12,7 +12,16 @@ pub use libc::sched_yield;
 
 extern {
     /// Change the data segment. See `man sbrk`.
-    pub fn sbrk(_: libc::intptr_t) -> *const libc::c_void;
+    pub fn sbrk(ptr: libc::intptr_t) -> *const libc::c_void;
+    /// Write a buffer to a file descriptor.
+    fn write(fd: libc::c_int, buff: *const libc::c_void, size: libc::size_t) -> libc::ssize_t;
+}
+
+/// Write to the log.
+///
+/// This points to stderr, but could be changed arbitrarily.
+pub fn log(s: &str) -> libc::ssize_t {
+    unsafe { write(2, s.as_ptr() as *const libc::c_void, s.len()) }
 }
 
 /// Thread destructors for Linux.

+ 1 - 4
src/bookkeeper.rs

@@ -191,7 +191,7 @@ impl Bookkeeper {
 
             if let Some((_, x)) = it.next() {
                 // Make sure there are no leading empty blocks.
-                assert!(!x.is_empty());
+                assert!(!x.is_empty(), "The leading block is empty.");
 
                 let mut next = x;
                 for (n, i) in it {
@@ -212,9 +212,6 @@ impl Bookkeeper {
                 // Check for trailing empty blocks.
                 assert!(!self.pool.last().unwrap().is_empty(), "Trailing empty blocks.");
             }
-
-            // Logging...
-            log!(self, "Check OK!");
         }
     }
 }

+ 2 - 1
src/fail.rs

@@ -68,7 +68,8 @@ pub fn set_thread_oom_handler(handler: fn() -> !) {
         let res = thread_oom.replace(Some(handler));
 
         // Make sure that it doesn't override another handler.
-        debug_assert!(res.is_none());
+        // TODO Make this a warning
+        debug_assert!(res.is_none(), "Overriding the old handler. Is this intentional?");
     });
 }
 

+ 4 - 4
src/log.rs

@@ -28,15 +28,15 @@ macro_rules! log {
             let _lock = write::LINE_LOCK.lock();
 
             // Print the pool state.
-            let mut stderr = write::Writer::stderr();
-            let _ = write!(stderr, "({:2})   {:10?} : ", $bk.id, log::internal::BlockLogger {
+            let mut log = write::Writer::new();
+            let _ = write!(log, "({:2})   {:10?} : ", $bk.id, log::internal::BlockLogger {
                 cur: $cur.clone().into_cursor(),
                 blocks: &$bk.pool,
             });
 
             // Print the log message.
-            let _ = write!(stderr, $( $arg ),*);
-            let _ = writeln!(stderr, " (at {}:{})", file!(), line!());
+            let _ = write!(log, $( $arg ),*);
+            let _ = writeln!(log, " (at {}:{})", file!(), line!());
         }
     };
 }

+ 9 - 0
src/sys.rs

@@ -61,6 +61,15 @@ pub fn register_thread_destructor<T>(load: *mut T, dtor: extern fn(*mut T)) -> R
     }
 }
 
+/// Write text to the log.
+///
+/// The log target is defined by the `shim` crate.
+// TODO find a better way to silence the warning than this attribute
+#[allow(dead_code)]
+pub fn log(s: &str) -> Result<(), ()> {
+    if shim::log(s) == -1 { Err(()) } else { Ok(()) }
+}
+
 #[cfg(test)]
 mod test {
     use super::*;

+ 13 - 19
src/write.rs

@@ -7,36 +7,28 @@ use prelude::*;
 
 use core::fmt;
 
-extern {
-    /// Write a buffer to a file descriptor.
-    fn write(fd: i32, buff: *const u8, size: usize) -> isize;
-}
+use sys;
 
 /// The line lock.
 ///
 /// This lock is used to avoid bungling and intertwining lines.
 pub static LINE_LOCK: Mutex<()> = Mutex::new(());
 
-/// A direct writer.
+/// A log writer.
 ///
-/// This writes directly to some file descriptor through the `write` symbol.
-pub struct Writer {
-    /// The file descriptor.
-    fd: i32,
-}
+/// This writes to  `sys::log`.
+pub struct Writer;
 
 impl Writer {
     /// Standard error output.
-    pub fn stderr() -> Writer {
-        Writer {
-            fd: 2,
-        }
+    pub fn new() -> Writer {
+        Writer
     }
 }
 
 impl fmt::Write for Writer {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        if unsafe { write(self.fd, s.as_ptr(), s.len()) } == !0 {
+        if sys::log(s).is_err() {
             Err(fmt::Error)
         } else { Ok(()) }
     }
@@ -61,9 +53,10 @@ macro_rules! assert {
             // To avoid cluttering the lines, we acquire a lock.
             let _lock = write::LINE_LOCK.lock();
 
-            let _ = write!(write::Writer::stderr(), "assertion failed at {}:{}: `{}` - ", file!(),
+            let mut log = write::Writer::new();
+            let _ = write!(log, "assertion failed at {}:{}: `{}` - ", file!(),
                            line!(), stringify!($e));
-            let _ = writeln!(write::Writer::stderr(), $( $arg ),*);
+            let _ = writeln!(log, $( $arg ),*);
 
             #[allow(unused_unsafe)]
             unsafe { intrinsics::abort() }
@@ -77,9 +70,10 @@ macro_rules! assert {
 /// allows for aborting, non-allocating panics when running the tests.
 #[macro_export]
 macro_rules! debug_assert {
-    ($( $arg:tt )*) => {{
+    // We force the programmer to provide explanation of their assertion.
+    ($first:expr, $( $arg:tt )*) => {{
         if cfg!(debug_assertions) {
-            assert!($( $arg )*);
+            assert!($first, $( $arg )*);
         }
     }}
 }