Remove legacy panic handling (#37947)

@maxdeviant We can eventually turn down the panic telemetry endpoint,
but should probably leave it up while there's still a bunch of stable
users hitting it.

@maxbrunsfeld We're optimistic that this change also fixed the macos
crashed-thread misreporting. We think it was because the
`CrashContext::exception` was getting set to `None` only on macos, while
on linux it was getting a real exception value from the sigtrap. Now
we've unified and it uses `SIGABRT` on both platforms (I need to double
check that this works as expected for windows).

We unconditionally set `RUST_BACKTRACE=1` for the current process so
that we see backtraces when running in a terminal by default. This
should be fine but I just wanted to note it since it's a bit abnormal.

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
Julia Ryan
2025-09-11 11:06:04 -07:00
committed by GitHub
co-authored by Conrad Irwin
parent 116c6549f6
commit a33af4e9c0
10 changed files with 69 additions and 544 deletions
+15 -104
View File
@@ -1,8 +1,8 @@
use crate::HeadlessProject;
use crate::headless_project::HeadlessAppState;
use anyhow::{Context as _, Result, anyhow};
use chrono::Utc;
use client::{ProxySettings, telemetry};
use client::ProxySettings;
use util::ResultExt;
use extension::ExtensionHostProxy;
use fs::{Fs, RealFs};
@@ -29,26 +29,23 @@ use reqwest_client::ReqwestClient;
use rpc::proto::{self, Envelope, REMOTE_SERVER_PROJECT_ID};
use rpc::{AnyProtoClient, TypedEnvelope};
use settings::{Settings, SettingsStore, watch_config_file};
use smol::Async;
use smol::channel::{Receiver, Sender};
use smol::io::AsyncReadExt;
use smol::Async;
use smol::{net::unix::UnixListener, stream::StreamExt as _};
use std::ffi::OsStr;
use std::ops::ControlFlow;
use std::process::ExitStatus;
use std::str::FromStr;
use std::sync::LazyLock;
use std::{env, thread};
use std::{
env,
ffi::OsStr,
fs::File,
io::Write,
mem,
ops::ControlFlow,
path::{Path, PathBuf},
sync::Arc,
process::ExitStatus,
str::FromStr,
sync::{Arc, LazyLock},
};
use telemetry_events::LocationData;
use thiserror::Error;
use util::ResultExt;
pub static VERSION: LazyLock<&str> = LazyLock::new(|| match *RELEASE_CHANNEL {
ReleaseChannel::Stable | ReleaseChannel::Preview => env!("ZED_PKG_VERSION"),
@@ -71,12 +68,12 @@ fn init_logging_proxy() {
fn init_logging_server(log_file_path: PathBuf) -> Result<Receiver<Vec<u8>>> {
struct MultiWrite {
file: std::fs::File,
file: File,
channel: Sender<Vec<u8>>,
buffer: Vec<u8>,
}
impl std::io::Write for MultiWrite {
impl Write for MultiWrite {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let written = self.file.write(buf)?;
self.buffer.extend_from_slice(&buf[..written]);
@@ -120,87 +117,6 @@ fn init_logging_server(log_file_path: PathBuf) -> Result<Receiver<Vec<u8>>> {
Ok(rx)
}
fn init_panic_hook(session_id: String) {
std::panic::set_hook(Box::new(move |info| {
let payload = info
.payload()
.downcast_ref::<&str>()
.map(|s| s.to_string())
.or_else(|| info.payload().downcast_ref::<String>().cloned())
.unwrap_or_else(|| "Box<Any>".to_string());
crashes::handle_panic(payload.clone(), info.location());
let backtrace = backtrace::Backtrace::new();
let mut backtrace = backtrace
.frames()
.iter()
.flat_map(|frame| {
frame
.symbols()
.iter()
.filter_map(|frame| Some(format!("{:#}", frame.name()?)))
})
.collect::<Vec<_>>();
// Strip out leading stack frames for rust panic-handling.
if let Some(ix) = backtrace
.iter()
.position(|name| name == "rust_begin_unwind")
{
backtrace.drain(0..=ix);
}
let thread = thread::current();
let thread_name = thread.name().unwrap_or("<unnamed>");
log::error!(
"panic occurred: {}\nBacktrace:\n{}",
&payload,
backtrace.join("\n")
);
let panic_data = telemetry_events::Panic {
thread: thread_name.into(),
payload,
location_data: info.location().map(|location| LocationData {
file: location.file().into(),
line: location.line(),
}),
app_version: format!("remote-server-{}", *VERSION),
app_commit_sha: option_env!("ZED_COMMIT_SHA").map(|sha| sha.into()),
release_channel: RELEASE_CHANNEL.dev_name().into(),
target: env!("TARGET").to_owned().into(),
os_name: telemetry::os_name(),
os_version: Some(telemetry::os_version()),
architecture: env::consts::ARCH.into(),
panicked_on: Utc::now().timestamp_millis(),
backtrace,
system_id: None, // Set on SSH client
installation_id: None, // Set on SSH client
// used on this end to associate panics with minidumps, but will be replaced on the SSH client
session_id: session_id.clone(),
};
if let Some(panic_data_json) = serde_json::to_string(&panic_data).log_err() {
let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
let panic_file_path = paths::logs_dir().join(format!("zed-{timestamp}.panic"));
let panic_file = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(&panic_file_path)
.log_err();
if let Some(mut panic_file) = panic_file {
writeln!(&mut panic_file, "{panic_data_json}").log_err();
panic_file.flush().log_err();
}
}
std::process::abort();
}));
}
fn handle_crash_files_requests(project: &Entity<HeadlessProject>, client: &AnyProtoClient) {
client.add_request_handler(
project.downgrade(),
@@ -249,10 +165,7 @@ fn handle_crash_files_requests(project: &Entity<HeadlessProject>, client: &AnyPr
}
}
anyhow::Ok(proto::GetCrashFilesResponse {
crashes,
legacy_panics,
})
anyhow::Ok(proto::GetCrashFilesResponse { crashes })
},
);
}
@@ -434,13 +347,12 @@ pub fn execute_run(
let id = std::process::id().to_string();
app.background_executor()
.spawn(crashes::init(crashes::InitCrashHandler {
session_id: id.clone(),
session_id: id,
zed_version: VERSION.to_owned(),
release_channel: release_channel::RELEASE_CHANNEL_NAME.clone(),
commit_sha: option_env!("ZED_COMMIT_SHA").unwrap_or("no_sha").to_owned(),
}))
.detach();
init_panic_hook(id);
let log_rx = init_logging_server(log_file)?;
log::info!(
"starting up. pid_file: {:?}, stdin_socket: {:?}, stdout_socket: {:?}, stderr_socket: {:?}",
@@ -627,13 +539,12 @@ pub(crate) fn execute_proxy(
let id = std::process::id().to_string();
smol::spawn(crashes::init(crashes::InitCrashHandler {
session_id: id.clone(),
session_id: id,
zed_version: VERSION.to_owned(),
release_channel: release_channel::RELEASE_CHANNEL_NAME.clone(),
commit_sha: option_env!("ZED_COMMIT_SHA").unwrap_or("no_sha").to_owned(),
}))
.detach();
init_panic_hook(id);
log::info!("starting proxy process. PID: {}", std::process::id());