update panic handler with system information

This commit is contained in:
Chance 2025-04-03 16:05:52 -04:00 committed by BitSyndicate
parent ed93baa404
commit ed23402212
4 changed files with 47 additions and 78 deletions

View file

@ -46,7 +46,7 @@ fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Err
};
writeln!(file, "{}", payload_str)?;
writeln!(file, "{}", render_backtrace().sanitize_path())?;
writeln!(file, "{}", capture_backtrace().sanitize_path())?;
let panic_msg = format!(
r#"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
@ -54,8 +54,7 @@ fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Err
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
https://codeberg.org/Caznix/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!"#,
@ -72,66 +71,28 @@ For future reference, the error summary is as follows:
println!("{}", final_msg.red().bold());
MessageDialog::new()
if let Err(e) = MessageDialog::new()
.set_type(MessageType::Error)
.set_title("A fatal error in Zenyx has occurred")
.set_text(&final_msg)
.show_alert()
.map_err(|e| {
error!("Failed to show error dialog: {}", e);
e.into()
})
}
fn render_backtrace() -> String {
const HEX_WIDTH: usize = mem::size_of::<usize>() * 2 + 2;
const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;
let mut backtrace = String::new();
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 {
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
let _ = writeln!(
backtrace,
"{:3$}at {}:{}",
"",
file.display(),
line,
NEXT_SYMBOL_PADDING
);
}
.show_confirm() {
error!("Failed to show message dialog: {e}")
}
}
Ok(())
}
fn capture_backtrace() -> String {
let mut backtrace = String::new();
let sysinfo = crate::metadata::SystemMetadata::current();
backtrace.push_str(&sysinfo.verbose_summary());
let trace = backtrace::Backtrace::new();
let message = format!("\nBacktrace:\n\n");
backtrace.push_str(&message);
backtrace.push_str(&format!("{trace:?}"));
backtrace
}

View file

@ -5,7 +5,6 @@ use std::time::Instant;
use cgmath::{Deg, Matrix4, Point3, Rad, SquareMatrix, Vector3, perspective};
use futures::executor::block_on;
use thiserror::Error;
use tracing::{debug, error, info, trace};
use wgpu::TextureUsages;
use wgpu::{Backends, InstanceDescriptor, util::DeviceExt};
@ -370,13 +369,12 @@ impl<'window> Renderer<'window> {
surface.configure(&device, &surface_config);
let (depth_texture, depth_texture_view) =
create_depth_texture(&device, surface_config.width, surface_config.height);
let (depth_texture, depth_texture_view) =
create_depth_texture(&device, surface_config.width, surface_config.height);
let font_bytes = include_bytes!("DejaVuSans.ttf");
let font = FontRef::try_from_slice(font_bytes).map_err(|e| {
ZenyxError::builder(ZenyxErrorKind::DeviceRequest)
ZenyxError::builder(ZenyxErrorKind::FontLoading)
.with_message("Font loading failed")
.with_source(e)
.build()
})?;

View file

@ -8,7 +8,6 @@ use std::sync::Arc;
use ctx::{Renderer, Vertex};
use image::ImageDecoder;
use image::ImageFormat;
use tobj::Mesh;
use tobj::{LoadOptions, Model};
use tracing::{debug, error, info, trace, warn};
use wgpu::rwh::HasWindowHandle;
@ -17,7 +16,6 @@ use winit::dpi::LogicalSize;
use winit::dpi::Size;
use winit::event::{KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::monitor::MonitorHandle;
use winit::platform::windows::WindowAttributesExtWindows;
use winit::window::Fullscreen;
use winit::window::Icon;
@ -94,15 +92,18 @@ f 6/11/6 5/10/6 1/1/6 2/13/6
";
impl App<'_> {
const ICON: &'static [u8] =
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/Badge.png"));
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
let icon = self.load_icon_from_bytes(Self::ICON).unwrap();
let win_attr = Window::default_attributes()
.with_title("Zenyx")
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
.with_window_icon(icon.clone())
.with_taskbar_icon(icon);
.with_title("Zenyx")
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
.with_window_icon(icon.clone())
.with_taskbar_icon(icon);
match event_loop.create_window(win_attr) {
Ok(window) => {
let window = Arc::new(window);
@ -229,14 +230,17 @@ impl App<'_> {
warn!("No window found for fullscreen toggle: {:?}", window_id);
}
}
fn load_icon_from_bytes(&self, bytes: &[u8]) -> Result<Option<Icon>, String> {
const IMAGE_DIR: &str = env!("CARGO_MANIFEST_DIR");
let cursor = Cursor::new(bytes);
let format = image::guess_format(bytes).map_err(|_| "Failed to guess image format")?;
let decoder = match format {
ImageFormat::Png => image::codecs::png::PngDecoder::new(cursor).map_err(|e| format!("Failed to decode PNG: {}", e))?,
ImageFormat::Png => image::codecs::png::PngDecoder::new(cursor)
.map_err(|e| format!("Failed to decode PNG: {}", e))?,
_ => {
let img = image::load_from_memory(bytes).map_err(|e| format!("Failed to load image: {}", e))?.into_rgba8();
let img = image::load_from_memory(bytes)
.map_err(|e| format!("Failed to load image: {}", e))?
.into_rgba8();
let (width, height) = img.dimensions();
return Icon::from_rgba(img.into_raw(), width, height)
.map(Some)
@ -246,14 +250,15 @@ impl App<'_> {
let (width, height) = decoder.dimensions();
let mut image_data = vec![0; decoder.total_bytes() as usize];
decoder.read_image(&mut image_data).map_err(|e| format!("Failed to read image data: {}", e))?;
decoder
.read_image(&mut image_data)
.map_err(|e| format!("Failed to read image data: {}", e))?;
Icon::from_rgba(image_data, width, height)
.map(Some)
.map_err(|e| format!("Failed to create icon from bytes: {}", e))
}
const ICON: &'static [u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/Badge.png"));
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
let title = format!("Zenyx - New Window {}", self.windows.len());
@ -265,7 +270,7 @@ impl App<'_> {
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
.with_window_icon(icon.clone())
.with_taskbar_icon(icon);
match main_ctx.window_handle() {
Ok(handle) => {
if !cfg!(target_os = "windows") {
@ -345,6 +350,11 @@ impl App<'_> {
fn handle_resize(&mut self, window_id: WindowId, new_size: winit::dpi::PhysicalSize<u32>) {
if let Some(window_context) = self.windows.get_mut(&window_id) {
// if we dont ignore size 0 this WILL cause a crash. DO NOT REMOVE
if new_size.height == 0 || new_size.width == 0 {
error!("Attempted to resize a window to 0x0!");
return;
}
window_context.ctx.resize(new_size.into());
window_context.window.request_redraw();
debug!(
@ -435,7 +445,7 @@ impl ApplicationHandler for App<'_> {
}
pub fn init_renderer(event_loop: EventLoop<()>) {
event_loop.set_control_flow(ControlFlow::Wait);
event_loop.set_control_flow(ControlFlow::Poll);
let mut app = App::default();
if let Err(e) = event_loop.run_app(&mut app) {
error!("Failed to run application: {}", e);

View file

@ -556,7 +556,7 @@ impl SystemMetadata {
};
format!(
"System Metadata:\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}",
"System Information:\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}",
self.cpu.verbose_info(),
main_gpu_info,
other_gpu_list,