update panic handler with system information
This commit is contained in:
parent
ed93baa404
commit
ed23402212
4 changed files with 47 additions and 78 deletions
|
@ -46,7 +46,7 @@ fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Err
|
||||||
};
|
};
|
||||||
|
|
||||||
writeln!(file, "{}", payload_str)?;
|
writeln!(file, "{}", payload_str)?;
|
||||||
writeln!(file, "{}", render_backtrace().sanitize_path())?;
|
writeln!(file, "{}", capture_backtrace().sanitize_path())?;
|
||||||
|
|
||||||
let panic_msg = format!(
|
let panic_msg = format!(
|
||||||
r#"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
|
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.
|
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:
|
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.
|
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!"#,
|
Thank you kindly!"#,
|
||||||
|
@ -72,66 +71,28 @@ For future reference, the error summary is as follows:
|
||||||
|
|
||||||
println!("{}", final_msg.red().bold());
|
println!("{}", final_msg.red().bold());
|
||||||
|
|
||||||
MessageDialog::new()
|
if let Err(e) = MessageDialog::new()
|
||||||
.set_type(MessageType::Error)
|
.set_type(MessageType::Error)
|
||||||
.set_title("A fatal error in Zenyx has occurred")
|
.set_title("A fatal error in Zenyx has occurred")
|
||||||
.set_text(&final_msg)
|
.set_text(&final_msg)
|
||||||
.show_alert()
|
.show_confirm() {
|
||||||
.map_err(|e| {
|
error!("Failed to show message dialog: {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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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
|
backtrace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use std::time::Instant;
|
||||||
|
|
||||||
use cgmath::{Deg, Matrix4, Point3, Rad, SquareMatrix, Vector3, perspective};
|
use cgmath::{Deg, Matrix4, Point3, Rad, SquareMatrix, Vector3, perspective};
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use thiserror::Error;
|
|
||||||
use tracing::{debug, error, info, trace};
|
use tracing::{debug, error, info, trace};
|
||||||
use wgpu::TextureUsages;
|
use wgpu::TextureUsages;
|
||||||
use wgpu::{Backends, InstanceDescriptor, util::DeviceExt};
|
use wgpu::{Backends, InstanceDescriptor, util::DeviceExt};
|
||||||
|
@ -370,13 +369,12 @@ impl<'window> Renderer<'window> {
|
||||||
surface.configure(&device, &surface_config);
|
surface.configure(&device, &surface_config);
|
||||||
let (depth_texture, depth_texture_view) =
|
let (depth_texture, depth_texture_view) =
|
||||||
create_depth_texture(&device, surface_config.width, surface_config.height);
|
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_bytes = include_bytes!("DejaVuSans.ttf");
|
||||||
let font = FontRef::try_from_slice(font_bytes).map_err(|e| {
|
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_message("Font loading failed")
|
||||||
|
.with_source(e)
|
||||||
.build()
|
.build()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ use std::sync::Arc;
|
||||||
use ctx::{Renderer, Vertex};
|
use ctx::{Renderer, Vertex};
|
||||||
use image::ImageDecoder;
|
use image::ImageDecoder;
|
||||||
use image::ImageFormat;
|
use image::ImageFormat;
|
||||||
use tobj::Mesh;
|
|
||||||
use tobj::{LoadOptions, Model};
|
use tobj::{LoadOptions, Model};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
use wgpu::rwh::HasWindowHandle;
|
use wgpu::rwh::HasWindowHandle;
|
||||||
|
@ -17,7 +16,6 @@ use winit::dpi::LogicalSize;
|
||||||
use winit::dpi::Size;
|
use winit::dpi::Size;
|
||||||
use winit::event::{KeyEvent, WindowEvent};
|
use winit::event::{KeyEvent, WindowEvent};
|
||||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||||
use winit::monitor::MonitorHandle;
|
|
||||||
use winit::platform::windows::WindowAttributesExtWindows;
|
use winit::platform::windows::WindowAttributesExtWindows;
|
||||||
use winit::window::Fullscreen;
|
use winit::window::Fullscreen;
|
||||||
use winit::window::Icon;
|
use winit::window::Icon;
|
||||||
|
@ -94,15 +92,18 @@ f 6/11/6 5/10/6 1/1/6 2/13/6
|
||||||
";
|
";
|
||||||
|
|
||||||
impl App<'_> {
|
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) {
|
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
let icon = self.load_icon_from_bytes(Self::ICON).unwrap();
|
let icon = self.load_icon_from_bytes(Self::ICON).unwrap();
|
||||||
|
|
||||||
let win_attr = Window::default_attributes()
|
let win_attr = Window::default_attributes()
|
||||||
.with_title("Zenyx")
|
.with_title("Zenyx")
|
||||||
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
|
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
|
||||||
.with_window_icon(icon.clone())
|
.with_window_icon(icon.clone())
|
||||||
.with_taskbar_icon(icon);
|
.with_taskbar_icon(icon);
|
||||||
|
|
||||||
match event_loop.create_window(win_attr) {
|
match event_loop.create_window(win_attr) {
|
||||||
Ok(window) => {
|
Ok(window) => {
|
||||||
let window = Arc::new(window);
|
let window = Arc::new(window);
|
||||||
|
@ -229,14 +230,17 @@ impl App<'_> {
|
||||||
warn!("No window found for fullscreen toggle: {:?}", window_id);
|
warn!("No window found for fullscreen toggle: {:?}", window_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_icon_from_bytes(&self, bytes: &[u8]) -> Result<Option<Icon>, String> {
|
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 cursor = Cursor::new(bytes);
|
||||||
let format = image::guess_format(bytes).map_err(|_| "Failed to guess image format")?;
|
let format = image::guess_format(bytes).map_err(|_| "Failed to guess image format")?;
|
||||||
let decoder = match 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();
|
let (width, height) = img.dimensions();
|
||||||
return Icon::from_rgba(img.into_raw(), width, height)
|
return Icon::from_rgba(img.into_raw(), width, height)
|
||||||
.map(Some)
|
.map(Some)
|
||||||
|
@ -246,14 +250,15 @@ impl App<'_> {
|
||||||
|
|
||||||
let (width, height) = decoder.dimensions();
|
let (width, height) = decoder.dimensions();
|
||||||
let mut image_data = vec![0; decoder.total_bytes() as usize];
|
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)
|
Icon::from_rgba(image_data, width, height)
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.map_err(|e| format!("Failed to create icon from bytes: {}", e))
|
.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) {
|
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||||
let title = format!("Zenyx - New Window {}", self.windows.len());
|
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_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
|
||||||
.with_window_icon(icon.clone())
|
.with_window_icon(icon.clone())
|
||||||
.with_taskbar_icon(icon);
|
.with_taskbar_icon(icon);
|
||||||
|
|
||||||
match main_ctx.window_handle() {
|
match main_ctx.window_handle() {
|
||||||
Ok(handle) => {
|
Ok(handle) => {
|
||||||
if !cfg!(target_os = "windows") {
|
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>) {
|
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 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.ctx.resize(new_size.into());
|
||||||
window_context.window.request_redraw();
|
window_context.window.request_redraw();
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -435,7 +445,7 @@ impl ApplicationHandler for App<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_renderer(event_loop: EventLoop<()>) {
|
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();
|
let mut app = App::default();
|
||||||
if let Err(e) = event_loop.run_app(&mut app) {
|
if let Err(e) = event_loop.run_app(&mut app) {
|
||||||
error!("Failed to run application: {}", e);
|
error!("Failed to run application: {}", e);
|
||||||
|
|
|
@ -556,7 +556,7 @@ impl SystemMetadata {
|
||||||
};
|
};
|
||||||
|
|
||||||
format!(
|
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(),
|
self.cpu.verbose_info(),
|
||||||
main_gpu_info,
|
main_gpu_info,
|
||||||
other_gpu_list,
|
other_gpu_list,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue