Skip to content

Commit

Permalink
polish repl (#17)
Browse files Browse the repository at this point in the history
* add less daunting panic message on release builds
  • Loading branch information
Caznix authored Dec 21, 2024
1 parent a1d8b65 commit dba07c4
Show file tree
Hide file tree
Showing 17 changed files with 405 additions and 106 deletions.
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ resolver = "2"
members = ["engine","subcrates/zen_core"]

[profile.dev]

rpath = false
panic = "abort"
lto = "off"
Expand All @@ -12,8 +13,9 @@ overflow-checks = false
incremental = true
codegen-units = 512


strip = "symbols"
debug-assertions = false
debug-assertions = true

[profile.dev.package."*"]
opt-level = 0
Expand All @@ -22,8 +24,9 @@ overflow-checks = false
incremental = true
codegen-units = 512


strip = "symbols"
debug-assertions = false
debug-assertions = true
[profile.dev.build-override]
opt-level = 0
debug = false
Expand All @@ -34,3 +37,6 @@ codegen-units = 512
[workspace.dependencies]
lazy_static = "1.5.0"
parking_lot = "0.12.3"

[profile.release]
debug-assertions = false
11 changes: 10 additions & 1 deletion engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
name = "engine"
version = "0.1.0"
edition = "2024"

repository = "https://github.com/Zenyx-Engine/Zenyx"
[dependencies]
anyhow = "1.0.94"
backtrace = "0.3.74"
chrono = "0.4.39"
colored = "2.2.0"
crashreport = "1.0.1"
dirs-next = "2.0.0"

lazy_static.workspace = true
log = "0.4.22"
Expand All @@ -15,3 +18,9 @@ parking_lot.workspace = true
regex = "1.11.1"
rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] }
tokio = { version = "1.42.0", features = ["macros", "parking_lot", "rt", "rt-multi-thread"] }

[profile.dev]
debug-assertions = true

[profile.release]
debug-assertions = false
3 changes: 3 additions & 0 deletions engine/src/core/ecs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// struct ComponentRegistry {
// components
// }
7 changes: 5 additions & 2 deletions engine/src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
pub mod repl;
pub mod ecs;
pub mod logger;
pub mod splash;
pub mod panic;
pub mod repl;
pub mod splash;
pub mod workspace;
152 changes: 152 additions & 0 deletions engine/src/core/panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
use std::fmt::Write as FmtWrite;
use std::mem;

use backtrace::Backtrace;
use parking_lot::Once;
use regex::Regex;

static INIT: parking_lot::Once = Once::new();

//#[cfg(not(debug_assertions))]
pub fn set_panic_hook() {
use std::io::Write;

use colored::Colorize;

use crate::workspace;
INIT.call_once(|| {
let default_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let log_path = workspace::get_working_dir().unwrap_or_else(|_| {
default_hook(info);
std::process::exit(0);
});
if !log_path.exists() {
std::fs::create_dir_all(&log_path).unwrap_or_else(|_| {
default_hook(info);
std::process::exit(0);
})
}
let log_path = log_path.join("panic.log");

// human_panic::print_msg::<PathBuf>(Some(log_path), &human_panic::Metadata::new("Zenyx", env!("CARGO_PKG_VERSION"))
// .support("https://github.com/Zenyx-Engine/Zenyx/issues")
// .authors("Zenyx community <https://github.com/Zenyx-Engine>")).unwrap();
// // Call the default hook for any additional actions

let mut file = std::fs::File::create(&log_path).unwrap_or_else(|_| {
default_hook(info);
std::process::exit(0);
});
writeln!(file, "{}", info.payload_as_str().unwrap_or_else(|| {
default_hook(info);
std::process::exit(0);
})).unwrap_or_else(|_| {
default_hook(info);
std::process::exit(0);
});
writeln!(file, "{}", render_backtrace().sanitize_path()).unwrap_or_else(|_| {
default_hook(info);
std::process::exit(0);
});
let panic_msg = format!(
"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
We have generated a report file at \"{}\". Submit an issue or email with the subject of \"Zenyx Crash Report\" and include the report as an attachment.
To submit the crash report:
https://github.com/Zenyx-Engine/Zenyx/issues
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
Thank you kindly!",log_path.display());
println!("{}",panic_msg.red().bold());
println!("\nFor future reference, the error summary is as follows:\n{}",info.payload_as_str().unwrap_or_else(||{
default_hook(info);
std::process::exit(0);
}).red().bold());
std::process::exit(0); // There is nothing to be done at this point, it looks cleaner to exit instead of doing a natural panic
}));
});
}
// THIS SNIPPET IS LICENSED UNDER THE APACHE LICENSE, VERSION 2.0
// https://github.com/rust-cli/human-panic
// No changes were made to the original snippet
fn render_backtrace() -> String {
//We take padding for address and extra two letters
//to pad after index.
#[allow(unused_qualifications)] // needed for pre-1.80 MSRV
const HEX_WIDTH: usize = mem::size_of::<usize>() * 2 + 2;
//Padding for next lines after frame's address
const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;

let mut backtrace = String::new();

//Here we iterate over backtrace frames
//(each corresponds to function's stack)
//We need to print its address
//and symbol(e.g. function name),
//if it is available
let bt = Backtrace::new();
let symbols = bt
.frames()
.iter()
.flat_map(|frame| {
let symbols = frame.symbols();
if symbols.is_empty() {
vec![(frame, None, "<unresolved>".to_owned())]
} else {
symbols
.iter()
.map(|s| {
(
frame,
Some(s),
s.name()
.map(|n| n.to_string())
.unwrap_or_else(|| "<unknown>".to_owned()),
)
})
.collect::<Vec<_>>()
}
})
.collect::<Vec<_>>();
let begin_unwind = "rust_begin_unwind";
let begin_unwind_start = symbols
.iter()
.position(|(_, _, n)| n == begin_unwind)
.unwrap_or(0);
for (entry_idx, (frame, symbol, name)) in symbols.iter().skip(begin_unwind_start).enumerate() {
let ip = frame.ip();
let _ = writeln!(backtrace, "{entry_idx:4}: {ip:HEX_WIDTH$?} - {name}");
if let Some(symbol) = symbol {
//See if there is debug information with file name and line
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
let _ = writeln!(
backtrace,
"{:3$}at {}:{}",
"",
file.display(),
line,
NEXT_SYMBOL_PADDING
);
}
}
}

backtrace
}

trait Sanitize {
fn sanitize_path(&self) -> String;
}

impl Sanitize for str {
fn sanitize_path(&self) -> String {
let username_pattern = r"(?i)(/home/|/Users/|\\Users\\)([^/\\]+)";
let re = Regex::new(username_pattern).expect("Failed to sanitize path, aborting operation");

re.replace_all(self, "${1}<USER>").to_string()
}
}
Loading

0 comments on commit dba07c4

Please sign in to comment.