use libc::c_void;
use mem;
use ptr;
-use sync::StaticMutex;
use sys::c;
use sys::dynamic_lib::DynamicLibrary;
+use sys::mutex::Mutex;
macro_rules! sym {
($lib:expr, $e:expr, $t:ident) => (
pub fn write(w: &mut Write) -> io::Result<()> {
// According to windows documentation, all dbghelp functions are
// single-threaded.
- static LOCK: StaticMutex = StaticMutex::new();
- let _g = LOCK.lock();
+ static LOCK: Mutex = Mutex::new();
+ unsafe {
+ LOCK.lock();
+ let res = _write(w);
+ LOCK.unlock();
+ return res
+ }
+}
+unsafe fn _write(w: &mut Write) -> io::Result<()> {
let dbghelp = match DynamicLibrary::open("dbghelp.dll") {
Ok(lib) => lib,
Err(..) => return Ok(()),
};
- unsafe {
- // Fetch the symbols necessary from dbghelp.dll
- let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn);
- let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn);
- let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
-
- // Allocate necessary structures for doing the stack walk
- let process = c::GetCurrentProcess();
- let thread = c::GetCurrentThread();
- let mut context: c::CONTEXT = mem::zeroed();
- c::RtlCaptureContext(&mut context);
- let mut frame: c::STACKFRAME64 = mem::zeroed();
- let image = init_frame(&mut frame, &context);
-
- // Initialize this process's symbols
- let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
- if ret != c::TRUE { return Ok(()) }
- let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
-
- // And now that we're done with all the setup, do the stack walking!
- // Start from -1 to avoid printing this stack frame, which will
- // always be exactly the same.
- let mut i = -1;
- write!(w, "stack backtrace:\n")?;
- while StackWalk64(image, process, thread, &mut frame, &mut context,
- ptr::null_mut(),
- ptr::null_mut(),
- ptr::null_mut(),
- ptr::null_mut()) == c::TRUE {
- let addr = frame.AddrPC.Offset;
- if addr == frame.AddrReturn.Offset || addr == 0 ||
- frame.AddrReturn.Offset == 0 { break }
-
- i += 1;
-
- if i >= 0 {
- printing::print(w, i, addr - 1, process, &dbghelp)?;
- }
- }
- Ok(())
+ // Fetch the symbols necessary from dbghelp.dll
+ let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn);
+ let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn);
+ let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
+
+ // Allocate necessary structures for doing the stack walk
+ let process = c::GetCurrentProcess();
+ let thread = c::GetCurrentThread();
+ let mut context: c::CONTEXT = mem::zeroed();
+ c::RtlCaptureContext(&mut context);
+ let mut frame: c::STACKFRAME64 = mem::zeroed();
+ let image = init_frame(&mut frame, &context);
+
+ // Initialize this process's symbols
+ let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
+ if ret != c::TRUE { return Ok(()) }
+ let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
+
+ // And now that we're done with all the setup, do the stack walking!
+ // Start from -1 to avoid printing this stack frame, which will
+ // always be exactly the same.
+ let mut i = -1;
+ write!(w, "stack backtrace:\n")?;
+ while StackWalk64(image, process, thread, &mut frame, &mut context,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut()) == c::TRUE {
+ let addr = frame.AddrPC.Offset;
+ if addr == frame.AddrReturn.Offset || addr == 0 ||
+ frame.AddrReturn.Offset == 0 { break }
+
+ i += 1;
+
+ if i >= 0 {
+ printing::print(w, i, addr - 1, process, &dbghelp)?;
+ }
}
+
+ Ok(())
}