Skip to content

Commit 7f3474f

Browse files
Jardynqaminya
authored andcommitted
Moved SuspendThread and ResumeThread inside of trace_impl on windows
1 parent fb115a7 commit 7f3474f

File tree

3 files changed

+28
-13
lines changed

3 files changed

+28
-13
lines changed

src/backtrace/dbghelp.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,23 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool, thread: *mut c_vo
9797
if thread == GetCurrentThread() || thread.is_null() {
9898
RtlCaptureContext(&mut context.0);
9999
} else {
100-
const CONTEXT_i386: u32 = 0x10000;
101-
const CONTEXT_CONTROL: u32 = CONTEXT_i386 | 0x01; // SS:SP, CS:IP, FLAGS, B;
102-
const CONTEXT_INTEGER: u32 = CONTEXT_i386 | 0x02; // AX, BX, CX, DX, SI, D;
103-
const CONTEXT_SEGMENTS: u32 = CONTEXT_i386 | 0x04; // DS, ES, FS, G;
104-
const CONTEXT_FLOATING_POINT: u32 = CONTEXT_i386 | 0x08; // 387 stat;
105-
const CONTEXT_DEBUG_REGISTERS: u32 = CONTEXT_i386 | 0x10; // DB 0-3,6,;
106-
const CONTEXT_EXTENDED_REGISTERS: u32 = CONTEXT_i386 | 0x20; // cpu specific extension;
107-
const CONTEXT_ALL: u32 = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS;
108-
109-
context.0.ContextFlags = CONTEXT_ALL; // TODO: Narrow down flags
100+
// The suspending and resuming of threads is very risky.
101+
// It can end in a deadlock if the current thread tries to access
102+
// an object thats been locked by the suspended thread.
103+
// That's why we only do as little work as possible while
104+
// the thread is suspended, and resume it quickly after.
105+
106+
// There is most definitely more pitfalls i haven't thought
107+
// of or encountered. This is windows after all.
108+
109+
context.0.ContextFlags = CONTEXT_ALL; // TODO: Narrow down required flags
110+
if SuspendThread(thread) as i32 == -1 {
111+
ResumeThread(thread);
112+
return;
113+
}
110114
let status = GetThreadContext(thread, &mut context.0);
111-
if status == 0 {
112-
return // GetThreadContext failed
115+
if ResumeThread(thread) as i32 == -1 || status == 0{
116+
return;
113117
}
114118
}
115119

src/backtrace/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
6767
}
6868

6969
/// TODO docs
70-
pub unsafe fn trace_thread_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F, thread: *mut c_void) {
70+
pub unsafe fn trace_thread_unsynchronized<F: FnMut(&Frame) -> bool>(thread: *mut c_void, mut cb: F) {
7171
trace_imp(&mut cb, thread)
7272
}
7373

src/windows.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,15 @@ ffi! {
346346
pub const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
347347
pub const MAX_MODULE_NAME32: usize = 255;
348348
pub const MAX_PATH: usize = 260;
349+
pub const CONTEXT_i386: u32 = 0x10000;
350+
pub const CONTEXT_CONTROL: u32 = CONTEXT_i386 | 0x01; // SS:SP, CS:IP, FLAGS, B;
351+
pub const CONTEXT_INTEGER: u32 = CONTEXT_i386 | 0x02; // AX, BX, CX, DX, SI, D;
352+
pub const CONTEXT_SEGMENTS: u32 = CONTEXT_i386 | 0x04; // DS, ES, FS, G;
353+
pub const CONTEXT_FLOATING_POINT: u32 = CONTEXT_i386 | 0x08; // 387 stat;
354+
pub const CONTEXT_DEBUG_REGISTERS: u32 = CONTEXT_i386 | 0x10; // DB 0-3,6,;
355+
pub const CONTEXT_EXTENDED_REGISTERS: u32 = CONTEXT_i386 | 0x20; // cpu specific extension;
356+
pub const CONTEXT_ALL: u32 = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS;
357+
349358

350359
pub type DWORD = u32;
351360
pub type PDWORD = *mut u32;
@@ -376,6 +385,8 @@ ffi! {
376385
pub fn GetCurrentThread() -> HANDLE;
377386
pub fn RtlCaptureContext(ContextRecord: PCONTEXT) -> ();
378387
pub fn GetThreadContext(ThreadHandle: HANDLE, ContextRecord: PCONTEXT) -> DWORD;
388+
pub fn SuspendThread(ThreadHandle: HANDLE) -> DWORD;
389+
pub fn ResumeThread(ThreadHandle: HANDLE) -> DWORD;
379390
pub fn LoadLibraryA(a: *const i8) -> HMODULE;
380391
pub fn GetProcAddress(h: HMODULE, name: *const i8) -> FARPROC;
381392
pub fn GetModuleHandleA(name: *const i8) -> HMODULE;

0 commit comments

Comments
 (0)