veilid_tools/
debugging.rs1#![cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
2
3use super::*;
4
5#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7pub enum DebuggerState {
8 Detached,
10 Attached,
12 Unknown,
14}
15
16#[must_use]
18#[allow(unreachable_code)]
19pub fn debugger_state() -> DebuggerState {
20 #[cfg(windows)]
21 unsafe {
22 return if winapi::um::debugapi::IsDebuggerPresent() == 0 {
23 DebuggerState::Detached
24 } else {
25 DebuggerState::Attached
26 };
27 }
28
29 #[cfg(any(target_os = "ios", target_os = "macos"))]
30 {
31 use libc::{c_int, c_void, getpid, size_t, sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PID};
32 const P_TRACED: u32 = 0x00800;
34 unsafe {
35 let mut info = [0u8; 648];
36 let mut size: size_t = info.len();
37 let mut mib: [c_int; 4] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()];
38 let ret = sysctl(
39 mib.as_mut_ptr(),
40 4,
41 info.as_mut_ptr() as *mut c_void,
42 &mut size as *mut size_t,
43 core::ptr::null_mut(),
44 0,
45 );
46 if ret == 0 {
47 return if (u32::from_le_bytes(info[32..36].try_into().unwrap()) & P_TRACED) != 0 {
48 DebuggerState::Attached
49 } else {
50 DebuggerState::Detached
51 };
52 }
53 }
54 }
55
56 #[cfg(unix)]
58 {
59 if let Ok(file) = std::fs::File::open("/proc/self/status") {
60 let file = std::io::BufReader::new(file);
61 use std::io::BufRead;
62 for line in file.lines().map_while(Result::ok) {
63 let line = line.trim();
64 if line.starts_with("TracerPid:") {
65 return match [" 0", "\t0", ":0"].iter().any(|zero| line.ends_with(zero)) {
66 true => DebuggerState::Detached,
67 false => DebuggerState::Attached,
68 };
69 }
70 }
71 }
72 }
73
74 DebuggerState::Unknown
75}
76
77pub fn wait_until_debugger_attached<T: Into<Option<Duration>>>(
79 timeout: T,
80) -> Result<(), &'static str> {
81 let timeout = timeout.into().map(|dur| std::time::Instant::now() + dur);
82 loop {
83 match debugger_state() {
84 DebuggerState::Attached => return Ok(()),
85 DebuggerState::Unknown => {
86 return Err("debugger state is unknown, cannot wait for attach")
87 }
88 DebuggerState::Detached => {
89 if let Some(timeout) = timeout {
90 if std::time::Instant::now() >= timeout {
91 return Err("wait for debugger attach timed out");
92 }
93 }
94 std::thread::sleep(Duration::from_millis(16));
95 }
96 }
97 }
98}