Improve backtraces when hovering widgets with modifiers pressed (#4696)
A useful debug-feature in egui is pressing down all modifiers keys and hovering any widget to see its backtrace (only in `dev` builds). Unfortunately this is incompatible with `panic="abort"`, something I just now discovered. So I removed `panic="abort"` from `Cargo.toml` for `dev` builds. If the backtrace returns empty-handed, I also suggests this as a fix to the user. Finally, I cleaned up the backtraces a bit, making them slightly shorter and more readable.
This commit is contained in:
parent
b1dc059ef3
commit
db8db50bf3
|
|
@ -43,7 +43,10 @@ panic = "abort" # This leads to better optimizations and smaller binaries (and i
|
|||
# split-debuginfo = "unpacked" # faster debug builds on mac
|
||||
# opt-level = 1 # Make debug builds run faster
|
||||
|
||||
panic = "abort" # This leads to better optimizations and smaller binaries (and is the default in Wasm anyways).
|
||||
# panic = "abort" leads to better optimizations and smaller binaries (and is the default in Wasm anyways),
|
||||
# but it also means backtraces don't work with the `backtrace` library (https://github.com/rust-lang/backtrace-rs/issues/397).
|
||||
# egui has a feature where if you hold down all modifiers keys on your keyboard and hover any UI widget,
|
||||
# you will see the backtrace to that widget, and we don't want to break that feature in dev builds.
|
||||
|
||||
[profile.dev.package."*"]
|
||||
# Optimize all dependencies even in debug builds (does not affect workspace packages):
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ struct Frame {
|
|||
///
|
||||
/// In particular: slips everything before `egui::Context::run`,
|
||||
/// and skipping all frames in the `egui::` namespace.
|
||||
#[inline(never)]
|
||||
pub fn capture() -> String {
|
||||
let mut frames = vec![];
|
||||
let mut depth = 0;
|
||||
|
|
@ -28,7 +29,7 @@ pub fn capture() -> String {
|
|||
|
||||
let name = symbol
|
||||
.name()
|
||||
.map(|name| name.to_string())
|
||||
.map(|name| clean_symbol_name(name.to_string()))
|
||||
.unwrap_or_default();
|
||||
|
||||
frames.push(Frame {
|
||||
|
|
@ -44,12 +45,13 @@ pub fn capture() -> String {
|
|||
});
|
||||
|
||||
if frames.is_empty() {
|
||||
return Default::default();
|
||||
return
|
||||
"Failed to capture a backtrace. A common cause of this is compiling with panic=\"abort\" (https://github.com/rust-lang/backtrace-rs/issues/397)".to_owned();
|
||||
}
|
||||
|
||||
// Inclusive:
|
||||
let mut min_depth = 0;
|
||||
let mut max_depth = frames.len() - 1;
|
||||
let mut max_depth = usize::MAX;
|
||||
|
||||
for frame in &frames {
|
||||
if frame.name.starts_with("egui::callstack::capture") {
|
||||
|
|
@ -60,14 +62,23 @@ pub fn capture() -> String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Is this the name of some sort of useful entry point?
|
||||
fn is_start_name(name: &str) -> bool {
|
||||
name == "main"
|
||||
|| name == "_main"
|
||||
|| name.starts_with("eframe::run_native")
|
||||
|| name.starts_with("egui::context::Context::run")
|
||||
}
|
||||
|
||||
let mut has_kept_any_start_names = false;
|
||||
|
||||
frames.reverse(); // main on top, i.e. chronological order. Same as Python.
|
||||
|
||||
// Remove frames that are uninteresting:
|
||||
frames.retain(|frame| {
|
||||
// Keep some special frames to give the user a sense of chronology:
|
||||
if frame.name == "main"
|
||||
|| frame.name == "_main"
|
||||
|| frame.name.starts_with("egui::context::Context::run")
|
||||
|| frame.name.starts_with("eframe::run_native")
|
||||
{
|
||||
// Keep the first "start" frame we can detect (e.g. `main`) to give the user a sense of chronology:
|
||||
if is_start_name(&frame.name) && !has_kept_any_start_names {
|
||||
has_kept_any_start_names = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -96,8 +107,6 @@ pub fn capture() -> String {
|
|||
true
|
||||
});
|
||||
|
||||
frames.reverse(); // main on top, i.e. chronological order. Same as Python.
|
||||
|
||||
let mut deepest_depth = 0;
|
||||
let mut widest_file_line = 0;
|
||||
for frame in &frames {
|
||||
|
|
@ -135,6 +144,28 @@ pub fn capture() -> String {
|
|||
formatted
|
||||
}
|
||||
|
||||
fn clean_symbol_name(mut s: String) -> String {
|
||||
// We get a hex suffix (at least on macOS) which is quite unhelpful,
|
||||
// e.g. `my_crate::my_function::h3bedd97b1e03baa5`.
|
||||
// Let's strip that.
|
||||
if let Some(h) = s.rfind("::h") {
|
||||
let hex = &s[h + 3..];
|
||||
if hex.len() == 16 && hex.chars().all(|c| c.is_ascii_hexdigit()) {
|
||||
s.truncate(h);
|
||||
}
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clean_symbol_name() {
|
||||
assert_eq!(
|
||||
clean_symbol_name("my_crate::my_function::h3bedd97b1e03baa5".to_owned()),
|
||||
"my_crate::my_function"
|
||||
);
|
||||
}
|
||||
|
||||
/// Shorten a path to a Rust source file from a callstack.
|
||||
///
|
||||
/// Example input:
|
||||
|
|
|
|||
Loading…
Reference in New Issue