mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Replace unwind-sys with backtrace crate on Linux (#37728)
This PR removes `unwind-sys` usage from background_hang_monitor on Linux, replacing it with the [backtrace crate](https://crates.io/crates/backtrace). Testing: `hang_monitor-tests.rs` still pass after the change (on Ubuntu 24.04). Fixes: https://github.com/servo/servo/issues/35063 --------- Signed-off-by: CarePackage17 <5157010+CarePackage17@users.noreply.github.com>
This commit is contained in:
parent
be1ebb8ad4
commit
a93d977020
3 changed files with 13 additions and 85 deletions
|
@ -28,7 +28,6 @@ mach2 = { version = "0.4", optional = true }
|
|||
|
||||
[target.'cfg(all(target_os = "linux", not(any(target_arch = "arm", target_arch = "aarch64", target_env = "ohos", target_env = "musl"))))'.dependencies]
|
||||
nix = { workspace = true, features = ["signal"], optional = true }
|
||||
unwind-sys = { version = "0.1.4", optional = true }
|
||||
|
||||
[features]
|
||||
sampler = ["unwind-sys", "mach2", "nix"]
|
||||
sampler = ["mach2", "nix"]
|
||||
|
|
|
@ -5,13 +5,9 @@
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use std::{cmp, io, mem, process, ptr, thread};
|
||||
use std::{io, mem, process, thread};
|
||||
|
||||
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
|
||||
use unwind_sys::{
|
||||
UNW_ESUCCESS, UNW_REG_IP, UNW_REG_SP, unw_cursor_t, unw_get_reg, unw_init_local, unw_step,
|
||||
};
|
||||
|
||||
use crate::sampler::{NativeStack, Sampler};
|
||||
|
||||
|
@ -27,8 +23,6 @@ static SHARED_STATE: UncheckedSyncUnsafeCell<SharedState> =
|
|||
msg4: None,
|
||||
}));
|
||||
|
||||
static CONTEXT: AtomicPtr<libc::ucontext_t> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
type MonitoredThreadId = libc::pid_t;
|
||||
|
||||
struct SharedState {
|
||||
|
@ -48,7 +42,6 @@ fn clear_shared_state() {
|
|||
shared_state.msg3 = None;
|
||||
shared_state.msg4 = None;
|
||||
}
|
||||
CONTEXT.store(ptr::null_mut(), Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn reset_shared_state() {
|
||||
|
@ -59,7 +52,6 @@ fn reset_shared_state() {
|
|||
shared_state.msg3 = Some(PosixSemaphore::new(0).expect("valid semaphore"));
|
||||
shared_state.msg4 = Some(PosixSemaphore::new(0).expect("valid semaphore"));
|
||||
}
|
||||
CONTEXT.store(ptr::null_mut(), Ordering::SeqCst);
|
||||
}
|
||||
|
||||
struct PosixSemaphore {
|
||||
|
@ -149,40 +141,6 @@ impl LinuxSampler {
|
|||
}
|
||||
}
|
||||
|
||||
enum RegNum {
|
||||
Ip = UNW_REG_IP as isize,
|
||||
Sp = UNW_REG_SP as isize,
|
||||
}
|
||||
|
||||
fn get_register(cursor: *mut unw_cursor_t, num: RegNum) -> Result<u64, i32> {
|
||||
unsafe {
|
||||
let mut val = 0;
|
||||
let ret = unw_get_reg(cursor, num as i32, &mut val);
|
||||
if ret == UNW_ESUCCESS {
|
||||
Ok(val)
|
||||
} else {
|
||||
Err(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn step(cursor: *mut unw_cursor_t) -> Result<bool, i32> {
|
||||
unsafe {
|
||||
// libunwind 1.1 seems to get confused and walks off the end of the stack. The last IP
|
||||
// it reports is 0, so we'll stop if we're there.
|
||||
if get_register(cursor, RegNum::Ip).unwrap_or(1) == 0 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let ret = unw_step(cursor);
|
||||
match ret.cmp(&0) {
|
||||
cmp::Ordering::Less => Err(ret),
|
||||
cmp::Ordering::Greater => Ok(true),
|
||||
cmp::Ordering::Equal => Ok(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sampler for LinuxSampler {
|
||||
#[allow(unsafe_code)]
|
||||
fn suspend_and_sample_thread(&self) -> Result<NativeStack, ()> {
|
||||
|
@ -209,33 +167,17 @@ impl Sampler for LinuxSampler {
|
|||
.wait_through_intr()
|
||||
.expect("msg2 failed");
|
||||
|
||||
let context = CONTEXT.load(Ordering::SeqCst);
|
||||
let mut cursor = mem::MaybeUninit::uninit();
|
||||
let ret = unsafe { unw_init_local(cursor.as_mut_ptr(), context) };
|
||||
result = if ret == UNW_ESUCCESS {
|
||||
let mut native_stack = NativeStack::new();
|
||||
#[allow(clippy::while_let_loop)] // False positive
|
||||
loop {
|
||||
let ip = match get_register(cursor.as_mut_ptr(), RegNum::Ip) {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => break,
|
||||
};
|
||||
let sp = match get_register(cursor.as_mut_ptr(), RegNum::Sp) {
|
||||
Ok(sp) => sp,
|
||||
Err(_) => break,
|
||||
};
|
||||
if native_stack
|
||||
.process_register(ip as *mut _, sp as *mut _)
|
||||
.is_err() ||
|
||||
!step(cursor.as_mut_ptr()).unwrap_or(false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(native_stack)
|
||||
} else {
|
||||
Err(())
|
||||
let mut native_stack = NativeStack::new();
|
||||
unsafe {
|
||||
backtrace::trace_unsynchronized(|frame| {
|
||||
let ip = frame.ip();
|
||||
let sp = frame.sp();
|
||||
|
||||
//This return value here determines whether we proceed to the next stack frame or not.
|
||||
native_stack.process_register(ip, sp).is_ok()
|
||||
})
|
||||
};
|
||||
result = Ok(native_stack);
|
||||
|
||||
// signal the thread to continue.
|
||||
shared_state
|
||||
|
@ -272,11 +214,9 @@ impl Drop for LinuxSampler {
|
|||
extern "C" fn sigprof_handler(
|
||||
sig: libc::c_int,
|
||||
_info: *mut libc::siginfo_t,
|
||||
ctx: *mut libc::c_void,
|
||||
_ctx: *mut libc::c_void,
|
||||
) {
|
||||
assert_eq!(sig, libc::SIGPROF);
|
||||
// copy the context.
|
||||
CONTEXT.store(ctx as *mut libc::ucontext_t, Ordering::SeqCst);
|
||||
|
||||
// Safety: non-exclusive reference only
|
||||
// since the sampling thread is accessing this concurrently
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue