mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 19:10:24 +00:00
Fix failure to upload panics when multiple panics happen at the same time (#2616)
When multiple panics occur at the same time (usually because one thread panics, and another thread joins it), multiple panic JSON objects can get written to the same panic file. The resulting file won't be valid JSON. This PR addresses that problem via two changes: * Format panic files as single-line JSON objects * When a panic file isn't valid JSON, try taking the first line In the future, we could try combining all of the backtraces, but for now, I just want to avoid a problem of not reporting a panic at all. Release Notes: - Fixed a problem with Zed's internal crash reporting.
This commit is contained in:
parent
16012fd800
commit
8910f7970b
1 changed files with 50 additions and 26 deletions
|
@ -435,12 +435,13 @@ fn init_panic_hook(app: &App) {
|
||||||
backtrace,
|
backtrace,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() {
|
|
||||||
if is_pty {
|
if is_pty {
|
||||||
|
if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() {
|
||||||
eprintln!("{}", panic_data_json);
|
eprintln!("{}", panic_data_json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
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 timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
|
||||||
let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp));
|
let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp));
|
||||||
let panic_file = std::fs::OpenOptions::new()
|
let panic_file = std::fs::OpenOptions::new()
|
||||||
|
@ -449,10 +450,11 @@ fn init_panic_hook(app: &App) {
|
||||||
.open(&panic_file_path)
|
.open(&panic_file_path)
|
||||||
.log_err();
|
.log_err();
|
||||||
if let Some(mut panic_file) = panic_file {
|
if let Some(mut panic_file) = panic_file {
|
||||||
write!(&mut panic_file, "{}\n", panic_data_json).log_err();
|
writeln!(&mut panic_file, "{}", panic_data_json).log_err();
|
||||||
panic_file.flush().log_err();
|
panic_file.flush().log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,12 +484,29 @@ fn upload_previous_panics(http: Arc<dyn HttpClient>, cx: &mut AppContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if telemetry_settings.diagnostics {
|
if telemetry_settings.diagnostics {
|
||||||
let panic_data_text = smol::fs::read_to_string(&child_path)
|
let panic_file_content = smol::fs::read_to_string(&child_path)
|
||||||
.await
|
.await
|
||||||
.context("error reading panic file")?;
|
.context("error reading panic file")?;
|
||||||
|
|
||||||
|
let panic = serde_json::from_str(&panic_file_content)
|
||||||
|
.ok()
|
||||||
|
.or_else(|| {
|
||||||
|
panic_file_content
|
||||||
|
.lines()
|
||||||
|
.next()
|
||||||
|
.and_then(|line| serde_json::from_str(line).ok())
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
log::error!(
|
||||||
|
"failed to deserialize panic file {:?}",
|
||||||
|
panic_file_content
|
||||||
|
);
|
||||||
|
None
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(panic) = panic {
|
||||||
let body = serde_json::to_string(&PanicRequest {
|
let body = serde_json::to_string(&PanicRequest {
|
||||||
panic: serde_json::from_str(&panic_data_text)?,
|
panic,
|
||||||
token: ZED_SECRET_CLIENT_TOKEN.into(),
|
token: ZED_SECRET_CLIENT_TOKEN.into(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -496,9 +515,14 @@ fn upload_previous_panics(http: Arc<dyn HttpClient>, cx: &mut AppContext) {
|
||||||
.redirect_policy(isahc::config::RedirectPolicy::Follow)
|
.redirect_policy(isahc::config::RedirectPolicy::Follow)
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.body(body.into())?;
|
.body(body.into())?;
|
||||||
let response = http.send(request).await.context("error sending panic")?;
|
let response =
|
||||||
|
http.send(request).await.context("error sending panic")?;
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
log::error!("Error uploading panic to server: {}", response.status());
|
log::error!(
|
||||||
|
"Error uploading panic to server: {}",
|
||||||
|
response.status()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue