#![doc(html_root_url = "http://alexcrichton.com/backtrace-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
extern crate libc;
extern crate debug_builders;
#[cfg(feature = "kernel32-sys")] extern crate kernel32;
#[cfg(feature = "winapi")] extern crate winapi;
#[cfg(feature = "dbghelp")] extern crate dbghelp;
#[macro_use]
extern crate cfg_if;
pub use backtrace::{trace, Frame};
mod backtrace;
pub use symbolize::{Symbol, resolve};
mod symbolize;
pub use demangle::demangle;
mod demangle;
#[allow(dead_code)]
struct Bomb {
enabled: bool,
}
#[allow(dead_code)]
impl Drop for Bomb {
fn drop(&mut self) {
if self.enabled {
panic!("cannot panic during the backtrace function");
}
}
}
#[allow(dead_code)]
mod lock {
use std::cell::Cell;
use std::mem;
use std::sync::{Once, Mutex, MutexGuard, ONCE_INIT};
pub struct LockGuard(MutexGuard<'static, ()>);
static mut LOCK: *mut Mutex<()> = 0 as *mut _;
static INIT: Once = ONCE_INIT;
thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false));
impl Drop for LockGuard {
fn drop(&mut self) {
LOCK_HELD.with(|slot| {
assert!(slot.get());
slot.set(false);
});
}
}
pub fn lock() -> Option<LockGuard> {
if LOCK_HELD.with(|l| l.get()) {
return None
}
LOCK_HELD.with(|s| s.set(true));
unsafe {
INIT.call_once(|| {
LOCK = mem::transmute(Box::new(Mutex::new(())));
});
Some(LockGuard((*LOCK).lock().unwrap()))
}
}
}
#[cfg(all(windows, feature = "dbghelp"))]
fn dbghelp_init() -> Box<std::any::Any> {
use winapi::*;
struct Cleanup { handle: HANDLE }
impl Drop for Cleanup {
fn drop(&mut self) {
unsafe { ::dbghelp::SymCleanup(self.handle); }
}
}
unsafe {
let ret = ::dbghelp::SymInitializeW(kernel32::GetCurrentProcess(),
0 as *mut _, TRUE);
if ret != TRUE {
Box::new(())
} else {
Box::new(Cleanup { handle: kernel32::GetCurrentProcess() })
}
}
}