Compare commits
3 Commits
fix-hard-c
...
cole/more-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6380d6c4e | ||
|
|
35b2a3dd63 | ||
|
|
512aad18e4 |
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -5346,6 +5346,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"raw-window-handle",
|
||||
"refineable",
|
||||
"reliability",
|
||||
"resvg",
|
||||
"schemars",
|
||||
"seahash",
|
||||
@@ -10261,6 +10262,13 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reliability"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"futures 0.3.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remote"
|
||||
version = "0.1.0"
|
||||
@@ -10321,6 +10329,7 @@ dependencies = [
|
||||
"project",
|
||||
"proto",
|
||||
"release_channel",
|
||||
"reliability",
|
||||
"remote",
|
||||
"reqwest_client",
|
||||
"rpc",
|
||||
@@ -16041,6 +16050,7 @@ dependencies = [
|
||||
"proto",
|
||||
"recent_projects",
|
||||
"release_channel",
|
||||
"reliability",
|
||||
"remote",
|
||||
"repl",
|
||||
"reqwest_client",
|
||||
|
||||
@@ -92,6 +92,7 @@ members = [
|
||||
"crates/refineable/derive_refineable",
|
||||
"crates/release_channel",
|
||||
"crates/remote",
|
||||
"crates/reliability",
|
||||
"crates/remote_server",
|
||||
"crates/repl",
|
||||
"crates/reqwest_client",
|
||||
@@ -279,6 +280,7 @@ proto = { path = "crates/proto" }
|
||||
recent_projects = { path = "crates/recent_projects" }
|
||||
refineable = { path = "crates/refineable" }
|
||||
release_channel = { path = "crates/release_channel" }
|
||||
reliability = { path = "crates/reliability" }
|
||||
remote = { path = "crates/remote" }
|
||||
remote_server = { path = "crates/remote_server" }
|
||||
repl = { path = "crates/repl" }
|
||||
|
||||
@@ -326,17 +326,23 @@ pub async fn post_panic(
|
||||
let payload = slack::WebhookBody::new(|w| {
|
||||
w.add_section(|s| s.text(slack::Text::markdown("Panic request".to_string())))
|
||||
.add_section(|s| {
|
||||
s.add_field(slack::Text::markdown(format!(
|
||||
"*Version:*\n {} ",
|
||||
panic.app_version
|
||||
)))
|
||||
.add_field({
|
||||
slack::Text::markdown(format!(
|
||||
"*OS:*\n{} {}",
|
||||
panic.os_name,
|
||||
panic.os_version.unwrap_or_default()
|
||||
))
|
||||
})
|
||||
let s = s
|
||||
.add_field(slack::Text::markdown(format!(
|
||||
"*Version:*\n {} ",
|
||||
panic.app_version
|
||||
)))
|
||||
.add_field({
|
||||
slack::Text::markdown(format!(
|
||||
"*OS:*\n{} {}",
|
||||
panic.os_name,
|
||||
panic.os_version.unwrap_or_default()
|
||||
))
|
||||
});
|
||||
if let Some(context) = panic.context.as_ref() {
|
||||
s.add_field(slack::Text::markdown(format!("*Context:* {context}")))
|
||||
} else {
|
||||
s
|
||||
}
|
||||
})
|
||||
.add_rich_text(|r| r.add_preformatted(|p| p.add_text(backtrace_with_summary)))
|
||||
});
|
||||
|
||||
@@ -146,6 +146,7 @@ pathfinder_geometry = "0.5"
|
||||
# Always used
|
||||
flume = "0.11"
|
||||
oo7 = "0.3.0"
|
||||
reliability.workspace = true
|
||||
|
||||
# Used in both windowing options
|
||||
ashpd = { workspace = true, optional = true }
|
||||
|
||||
@@ -490,11 +490,19 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
.get("username")
|
||||
.ok_or_else(|| anyhow!("Cannot find username in stored credentials"))?;
|
||||
// oo7 panics if the retrieved secret can't be decrypted due to
|
||||
// unexpected padding.
|
||||
let secret = AssertUnwindSafe(item.secret())
|
||||
.catch_unwind()
|
||||
.await
|
||||
.map_err(|_| anyhow!("oo7 panicked while trying to read credentials"))??;
|
||||
// unexpected padding. Gather a little bit of extra information
|
||||
// to understand what's up. Don't Debug-print here since that includes secrets!
|
||||
let backend = match keyring {
|
||||
oo7::Keyring::File { .. } => "file",
|
||||
oo7::Keyring::DBus { .. } => "DBus",
|
||||
};
|
||||
let is_sandboxed = oo7::is_sandboxed().await;
|
||||
let secret = reliability::hook_fn(move |_| {
|
||||
format!("oo7 backend: {backend}, sandboxed: {is_sandboxed}")
|
||||
})
|
||||
.catch_unwind_future(item.secret())
|
||||
.await
|
||||
.map_err(|_| anyhow!("oo7 panicked while trying to read credentials"))??;
|
||||
|
||||
// we lose the zeroizing capabilities at this boundary,
|
||||
// a current limitation GPUI's credentials api
|
||||
|
||||
17
crates/reliability/Cargo.toml
Normal file
17
crates/reliability/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "reliability"
|
||||
description = "Provide scoped context for panics"
|
||||
edition = "2021"
|
||||
version = "0.1.0"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lib]
|
||||
path = "src/reliability.rs"
|
||||
doctest = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
futures.workspace = true
|
||||
1
crates/reliability/LICENSE-GPL
Symbolic link
1
crates/reliability/LICENSE-GPL
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE-GPL
|
||||
68
crates/reliability/src/reliability.rs
Normal file
68
crates/reliability/src/reliability.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use futures::FutureExt as _;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
future::Future,
|
||||
panic::{AssertUnwindSafe, PanicHookInfo},
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
static GLOBAL_HOOK: RefCell<Option<Box<dyn ReliabilityHook + Send + Sync>>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
pub trait ReliabilityHook {
|
||||
fn contextualize_panic(&self, info: &PanicHookInfo<'_>) -> String;
|
||||
}
|
||||
|
||||
impl<F> ReliabilityHook for F
|
||||
where
|
||||
F: Fn(&PanicHookInfo<'_>) -> String,
|
||||
{
|
||||
fn contextualize_panic(&self, info: &PanicHookInfo<'_>) -> String {
|
||||
self(info)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Guard(Option<Box<dyn ReliabilityHook + Send + Sync>>);
|
||||
|
||||
pub fn hook_fn(f: impl 'static + Send + Sync + Fn(&PanicHookInfo<'_>) -> String) -> Guard {
|
||||
GLOBAL_HOOK.with_borrow_mut(|global| {
|
||||
let old = std::mem::replace(global, Some(Box::new(f)));
|
||||
Guard(old)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_hook<R>(
|
||||
f: impl FnOnce(&(dyn ReliabilityHook + Send + Sync + 'static)) -> R,
|
||||
) -> Option<R> {
|
||||
let result = GLOBAL_HOOK.with_borrow(|global| {
|
||||
let global = &**global.as_ref()?;
|
||||
Some(f(global))
|
||||
})?;
|
||||
Some(result)
|
||||
}
|
||||
|
||||
impl Guard {
|
||||
pub fn catch_unwind<R>(&self, f: impl FnOnce() -> R) -> std::thread::Result<R> {
|
||||
std::panic::catch_unwind(AssertUnwindSafe(f))
|
||||
}
|
||||
|
||||
pub async fn catch_unwind_future<R>(
|
||||
&self,
|
||||
f: impl Future<Output = R>,
|
||||
) -> std::thread::Result<R> {
|
||||
AssertUnwindSafe(async {
|
||||
let _self = self;
|
||||
f.await
|
||||
})
|
||||
.catch_unwind()
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Guard {
|
||||
fn drop(&mut self) {
|
||||
GLOBAL_HOOK.with_borrow_mut(|global| {
|
||||
std::mem::swap(&mut self.0, global);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ paths = { workspace = true }
|
||||
project.workspace = true
|
||||
proto.workspace = true
|
||||
release_channel.workspace = true
|
||||
reliability.workspace = true
|
||||
remote.workspace = true
|
||||
reqwest_client.workspace = true
|
||||
rpc.workspace = true
|
||||
|
||||
@@ -148,6 +148,8 @@ fn init_panic_hook() {
|
||||
(&backtrace).join("\n")
|
||||
);
|
||||
|
||||
let context = reliability::with_hook(|hook| hook.contextualize_panic(info));
|
||||
|
||||
let panic_data = telemetry_events::Panic {
|
||||
thread: thread_name.into(),
|
||||
payload: payload.clone(),
|
||||
@@ -165,6 +167,7 @@ fn init_panic_hook() {
|
||||
architecture: env::consts::ARCH.into(),
|
||||
panicked_on: Utc::now().timestamp_millis(),
|
||||
backtrace,
|
||||
context,
|
||||
system_id: None, // Set on SSH client
|
||||
installation_id: None, // Set on SSH client
|
||||
session_id: "".to_string(), // Set on SSH client
|
||||
|
||||
@@ -258,6 +258,8 @@ pub struct Panic {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub location_data: Option<LocationData>,
|
||||
pub backtrace: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub context: Option<String>,
|
||||
/// Zed version number
|
||||
pub app_version: String,
|
||||
/// Zed release channel (stable, preview, dev)
|
||||
|
||||
@@ -89,6 +89,7 @@ project_symbols.workspace = true
|
||||
proto.workspace = true
|
||||
recent_projects.workspace = true
|
||||
release_channel.workspace = true
|
||||
reliability.workspace = true
|
||||
remote.workspace = true
|
||||
repl.workspace = true
|
||||
reqwest_client.workspace = true
|
||||
|
||||
@@ -90,6 +90,8 @@ pub fn init_panic_hook(
|
||||
backtrace.drain(0..=ix);
|
||||
}
|
||||
|
||||
let context = reliability::with_hook(|hook| hook.contextualize_panic(info));
|
||||
|
||||
let panic_data = telemetry_events::Panic {
|
||||
thread: thread_name.into(),
|
||||
payload,
|
||||
@@ -104,6 +106,7 @@ pub fn init_panic_hook(
|
||||
architecture: env::consts::ARCH.into(),
|
||||
panicked_on: Utc::now().timestamp_millis(),
|
||||
backtrace,
|
||||
context,
|
||||
system_id: system_id.clone(),
|
||||
installation_id: installation_id.clone(),
|
||||
session_id: session_id.clone(),
|
||||
|
||||
Reference in New Issue
Block a user