Avoid suspending panicking thread while crashing (#36645)
On the latest build @maxbrunsfeld got a panic that hung zed. It appeared that the hang occured after the minidump had been successfully written, so our theory on what happened is that the `suspend_all_other_threads` call in the crash handler suspended the panicking thread (due to the signal from simulate_exception being received on a different thread), and then when the crash handler returned everything was suspended so the panic hook never made it to the `process::abort`. This change makes the crash handler avoid _both_ the current and the panicking thread which should avoid that scenario. Release Notes: - N/A
This commit is contained in:
parent
7f1bd2f15e
commit
c5ee3f3e2e
1 changed files with 14 additions and 1 deletions
|
@ -4,6 +4,8 @@ use minidumper::{Client, LoopAction, MinidumpBinary};
|
||||||
use release_channel::{RELEASE_CHANNEL, ReleaseChannel};
|
use release_channel::{RELEASE_CHANNEL, ReleaseChannel};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use std::sync::atomic::AtomicU32;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
|
@ -26,6 +28,9 @@ pub static REQUESTED_MINIDUMP: AtomicBool = AtomicBool::new(false);
|
||||||
const CRASH_HANDLER_PING_TIMEOUT: Duration = Duration::from_secs(60);
|
const CRASH_HANDLER_PING_TIMEOUT: Duration = Duration::from_secs(60);
|
||||||
const CRASH_HANDLER_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
const CRASH_HANDLER_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
static PANIC_THREAD_ID: AtomicU32 = AtomicU32::new(0);
|
||||||
|
|
||||||
pub async fn init(crash_init: InitCrashHandler) {
|
pub async fn init(crash_init: InitCrashHandler) {
|
||||||
if *RELEASE_CHANNEL == ReleaseChannel::Dev && env::var("ZED_GENERATE_MINIDUMPS").is_err() {
|
if *RELEASE_CHANNEL == ReleaseChannel::Dev && env::var("ZED_GENERATE_MINIDUMPS").is_err() {
|
||||||
return;
|
return;
|
||||||
|
@ -110,9 +115,10 @@ unsafe fn suspend_all_other_threads() {
|
||||||
mach2::task::task_threads(task, &raw mut threads, &raw mut count);
|
mach2::task::task_threads(task, &raw mut threads, &raw mut count);
|
||||||
}
|
}
|
||||||
let current = unsafe { mach2::mach_init::mach_thread_self() };
|
let current = unsafe { mach2::mach_init::mach_thread_self() };
|
||||||
|
let panic_thread = PANIC_THREAD_ID.load(Ordering::SeqCst);
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
let t = unsafe { *threads.add(i as usize) };
|
let t = unsafe { *threads.add(i as usize) };
|
||||||
if t != current {
|
if t != current && t != panic_thread {
|
||||||
unsafe { mach2::thread_act::thread_suspend(t) };
|
unsafe { mach2::thread_act::thread_suspend(t) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,6 +244,13 @@ pub fn handle_panic(message: String, span: Option<&Location>) {
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
log::error!("triggering a crash to generate a minidump...");
|
log::error!("triggering a crash to generate a minidump...");
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
PANIC_THREAD_ID.store(
|
||||||
|
unsafe { mach2::mach_init::mach_thread_self() },
|
||||||
|
Ordering::SeqCst,
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
CrashHandler.simulate_signal(crash_handler::Signal::Trap as u32);
|
CrashHandler.simulate_signal(crash_handler::Signal::Trap as u32);
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue