Skip to content

Commit

Permalink
fix: add a separate trace_thread function
Browse files Browse the repository at this point in the history
  • Loading branch information
aminya committed Jul 10, 2022
1 parent f7d4e6d commit 68e1927
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 15 deletions.
10 changes: 4 additions & 6 deletions examples/other_thread.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Windows only currently
use std::os::windows::prelude::AsRawHandle;
use backtrace::{Backtrace, BacktraceFrame};

use std::os::windows::prelude::AsRawHandle;

fn worker() {
foo();
Expand All @@ -18,22 +17,21 @@ fn baz() {
//std::thread::sleep(std::time::Duration::from_millis(1000));
loop {
print!("");
};
}
}


fn main() {
let thread = std::thread::spawn(|| {
worker();
});
let os_handle = thread.as_raw_handle();

// Allow the thread to start
std::thread::sleep(std::time::Duration::from_millis(100));

let mut frames = Vec::new();
unsafe {
backtrace::trace_thread_unsynchronized(os_handle,|frame| {
backtrace::trace_thread_unsynchronized(os_handle, |frame| {
frames.push(BacktraceFrame::from(frame.clone()));
true
});
Expand Down
13 changes: 9 additions & 4 deletions src/backtrace/dbghelp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,14 @@ impl Frame {
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
struct MyContext(CONTEXT);

//#[inline(always)]
pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool, thread: *mut c_void) {
#[inline(always)]
pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) {
let thread = GetCurrentThread();
trace_thread(cb, thread)
}

#[inline(always)]
pub unsafe fn trace_thread(cb: &mut dyn FnMut(&super::Frame) -> bool, thread: *mut c_void) {
// Allocate necessary structures for doing the stack walk
let process = GetCurrentProcess();

Expand All @@ -112,12 +118,11 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool, thread: *mut c_vo
return;
}
let status = GetThreadContext(thread, &mut context.0);
if ResumeThread(thread) as i32 == -1 || status == 0{
if ResumeThread(thread) as i32 == -1 || status == 0 {
return;
}
}


// Ensure this process's symbols are initialized
let dbghelp = match dbghelp::init() {
Ok(dbghelp) => dbghelp,
Expand Down
23 changes: 19 additions & 4 deletions src/backtrace/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use core::ffi::c_void;
use core::fmt;

use self::dbghelp::trace_thread;

/// Inspects the current call-stack, passing all active frames into the closure
/// provided to calculate a stack trace.
///
Expand Down Expand Up @@ -63,12 +65,25 @@ pub fn trace<F: FnMut(&Frame) -> bool>(cb: F) {
///
/// See information on `trace` for caveats on `cb` panicking.
pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
trace_imp(&mut cb, 0 as _)
trace_imp(&mut cb)
}

/// TODO docs
pub unsafe fn trace_thread_unsynchronized<F: FnMut(&Frame) -> bool>(thread: *mut c_void, mut cb: F) {
trace_imp(&mut cb, thread)
/// Similar to [trace_unsynchronized], but additionally, it supports tracing a thread other than the current thread.
///
/// The function gets the traced thread's handle as its first argument.
///
/// This function does not have synchronization guarantees but is available
/// when the `std` feature of this crate isn't compiled in. See the `trace`
/// function for more documentation and examples.
///
/// # Panics
///
/// See information on `trace` for caveats on `cb` panicking.
pub unsafe fn trace_thread_unsynchronized<F: FnMut(&Frame) -> bool>(
thread: *mut c_void,
mut cb: F,
) {
trace_thread(&mut cb, thread)
}

/// A trait representing one frame of a backtrace, yielded to the `trace`
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ extern crate std;
#[allow(unused_extern_crates)]
extern crate alloc;

pub use self::backtrace::{trace_unsynchronized, trace_thread_unsynchronized, Frame};
pub use self::backtrace::{trace_thread_unsynchronized, trace_unsynchronized, Frame};
mod backtrace;

pub use self::symbolize::resolve_frame_unsynchronized;
Expand Down

0 comments on commit 68e1927

Please sign in to comment.