mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'xvar/better-voxygen-panic-messages' into 'master'
Reworked panic dialog to support displaying the likely cause of common panics See merge request veloren/veloren!3589
This commit is contained in:
commit
7aa1feea22
@ -12,7 +12,8 @@
|
||||
option_get_or_insert_default,
|
||||
map_try_insert,
|
||||
slice_as_chunks,
|
||||
unzip_option
|
||||
unzip_option,
|
||||
let_chains
|
||||
)]
|
||||
#![recursion_limit = "2048"]
|
||||
|
||||
@ -30,6 +31,7 @@ pub mod hud;
|
||||
pub mod key_state;
|
||||
pub mod menu;
|
||||
pub mod mesh;
|
||||
pub mod panic_handler;
|
||||
pub mod profile;
|
||||
pub mod render;
|
||||
pub mod run;
|
||||
|
@ -20,6 +20,7 @@ static GLOBAL: common_base::tracy_client::ProfiledAllocator<std::alloc::System>
|
||||
use i18n::{self, LocalizationHandle};
|
||||
use veloren_voxygen::{
|
||||
audio::AudioFrontend,
|
||||
panic_handler,
|
||||
profile::Profile,
|
||||
run,
|
||||
scene::terrain::SpriteRenderContext,
|
||||
@ -33,7 +34,7 @@ use chrono::Utc;
|
||||
use common::assets;
|
||||
use common::clock::Clock;
|
||||
use std::{panic, path::PathBuf};
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{info, warn};
|
||||
#[cfg(feature = "egui-ui")]
|
||||
use veloren_voxygen::ui::egui::EguiState;
|
||||
|
||||
@ -87,101 +88,7 @@ fn main() {
|
||||
panic!("Failed to save settings: {:?}", err);
|
||||
}
|
||||
|
||||
// Set up panic handler to relay swish panic messages to the user
|
||||
let default_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
let panic_info_payload = panic_info.payload();
|
||||
let payload_string = panic_info_payload.downcast_ref::<String>();
|
||||
let reason = match payload_string {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
let payload_str = panic_info_payload.downcast_ref::<&str>();
|
||||
match payload_str {
|
||||
Some(st) => st,
|
||||
None => "Payload is not a string",
|
||||
}
|
||||
},
|
||||
};
|
||||
let msg = format!(
|
||||
"A critical error has occurred and Voxygen has been forced to \
|
||||
terminate in an unusual manner. Details about the error can be \
|
||||
found below.\n\
|
||||
\n\
|
||||
> What should I do?\n\
|
||||
\n\
|
||||
We need your help to fix this! You can help by contacting us and \
|
||||
reporting this problem. To do this, open an issue on the Veloren \
|
||||
issue tracker:\n\
|
||||
\n\
|
||||
https://www.gitlab.com/veloren/veloren/issues/new\n\
|
||||
\n\
|
||||
If you're on the Veloren community Discord server, we'd be \
|
||||
grateful if you could also post a message in the #support channel.
|
||||
\n\
|
||||
> What should I include?\n\
|
||||
\n\
|
||||
The error information below will be useful in finding and fixing \
|
||||
the problem. Please include as much information about your setup \
|
||||
and the events that led up to the panic as possible.
|
||||
\n\
|
||||
Voxygen has logged information about the problem (including this \
|
||||
message) to the file {}. Please include the contents of this \
|
||||
file in your bug report.
|
||||
\n\
|
||||
> Error information\n\
|
||||
\n\
|
||||
The information below is intended for developers and testers.\n\
|
||||
\n\
|
||||
Panic Payload: {:?}\n\
|
||||
PanicInfo: {}\n\
|
||||
Game version: {} [{}]",
|
||||
logs_dir.join(&log_filename).display(),
|
||||
reason,
|
||||
panic_info,
|
||||
*common::util::GIT_HASH,
|
||||
*common::util::GIT_DATE
|
||||
);
|
||||
|
||||
error!(
|
||||
"VOXYGEN HAS PANICKED\n\n{}\n\nBacktrace:\n{:?}",
|
||||
msg,
|
||||
backtrace::Backtrace::new(),
|
||||
);
|
||||
|
||||
#[cfg(feature = "native-dialog")]
|
||||
{
|
||||
use native_dialog::{MessageDialog, MessageType};
|
||||
|
||||
let mbox = move || {
|
||||
MessageDialog::new()
|
||||
.set_title("Voxygen has panicked")
|
||||
//somehow `<` and `>` are invalid characters and cause the msg to get replaced
|
||||
// by some generic text thus i replace them
|
||||
.set_text(&msg.replace('<', "[").replace('>', "]"))
|
||||
.set_type(MessageType::Error)
|
||||
.show_alert()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// On windows we need to spawn a thread as the msg doesn't work otherwise
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let builder = std::thread::Builder::new().name("shutdown".into());
|
||||
builder
|
||||
.spawn(move || {
|
||||
mbox();
|
||||
})
|
||||
.unwrap()
|
||||
.join()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mbox();
|
||||
}
|
||||
|
||||
default_hook(panic_info);
|
||||
}));
|
||||
panic_handler::set_panic_hook(log_filename, logs_dir);
|
||||
|
||||
// Process CLI arguments
|
||||
use clap::Parser;
|
||||
|
143
voxygen/src/panic_handler.rs
Normal file
143
voxygen/src/panic_handler.rs
Normal file
@ -0,0 +1,143 @@
|
||||
use std::{panic, panic::PanicInfo, path::PathBuf};
|
||||
use tracing::error;
|
||||
|
||||
pub fn set_panic_hook(log_filename: String, logs_dir: PathBuf) {
|
||||
// Set up panic handler to relay swish panic messages to the user
|
||||
let default_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
let panic_info_payload = panic_info.payload();
|
||||
let payload_string = panic_info_payload.downcast_ref::<String>();
|
||||
let reason = match payload_string {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
let payload_str = panic_info_payload.downcast_ref::<&str>();
|
||||
match payload_str {
|
||||
Some(st) => st,
|
||||
None => "Payload is not a string",
|
||||
}
|
||||
},
|
||||
};
|
||||
let potential_cause = potential_cause(panic_info);
|
||||
|
||||
let mut dialog_message = format!(
|
||||
"A critical error has occurred and Voxygen has been forced to terminate in an unusual \
|
||||
manner. Details about the error can be found below.\n\nPanic reason: {}\n\n",
|
||||
reason
|
||||
);
|
||||
|
||||
if let Some(potential_cause) = potential_cause {
|
||||
// The error is a known error, so don't show the full bug report instructions
|
||||
// and instead show a potential fix.
|
||||
dialog_message.push_str(format!("Potential causes: {}\n\n", potential_cause).as_str())
|
||||
} else {
|
||||
dialog_message.push_str(
|
||||
format!("> What should I do?\n\
|
||||
\n\
|
||||
We need your help to fix this! You can help by contacting us and \
|
||||
reporting this problem. To do this, open an issue on the Veloren \
|
||||
issue tracker:\n\
|
||||
\n\
|
||||
https://www.gitlab.com/veloren/veloren/issues/new\n\
|
||||
\n\
|
||||
If you're on the Veloren community Discord server, we'd be \
|
||||
grateful if you could also post a message in the #support channel.
|
||||
\n\
|
||||
> What should I include?\n\
|
||||
\n\
|
||||
The error information below will be useful in finding and fixing \
|
||||
the problem. Please include as much information about your setup \
|
||||
and the events that led up to the panic as possible.
|
||||
\n\
|
||||
Voxygen has logged information about the problem (including this \
|
||||
message) to the file {}. Please include the contents of this \
|
||||
file in your bug report.
|
||||
\n\n", logs_dir.join(&log_filename).display())
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
dialog_message.push_str(
|
||||
format!(
|
||||
"> Error information\n\nThe information below is intended for developers and \
|
||||
testers.\n\nPanicInfo: {} \nGame version: {} [{}]",
|
||||
panic_info,
|
||||
*common::util::GIT_HASH,
|
||||
*common::util::GIT_DATE
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
|
||||
error!(
|
||||
"VOXYGEN HAS PANICKED\n\n{}\n\nBacktrace:\n{:?}",
|
||||
dialog_message,
|
||||
backtrace::Backtrace::new(),
|
||||
);
|
||||
|
||||
#[cfg(feature = "native-dialog")]
|
||||
{
|
||||
use native_dialog::{MessageDialog, MessageType};
|
||||
|
||||
let mbox = move || {
|
||||
MessageDialog::new()
|
||||
.set_title("Veloren has crashed!")
|
||||
//somehow `<` and `>` are invalid characters and cause the msg to get replaced
|
||||
// by some generic text thus i replace them
|
||||
.set_text(&dialog_message.replace('<', "[").replace('>', "]"))
|
||||
.set_type(MessageType::Error)
|
||||
.show_alert()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// On windows we need to spawn a thread as the msg doesn't work otherwise
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let builder = std::thread::Builder::new().name("shutdown".into());
|
||||
builder
|
||||
.spawn(move || {
|
||||
mbox();
|
||||
})
|
||||
.unwrap()
|
||||
.join()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mbox();
|
||||
}
|
||||
|
||||
default_hook(panic_info);
|
||||
}));
|
||||
}
|
||||
|
||||
enum PotentialPanicCause {
|
||||
GraphicsCardIncompatibleWithRenderingBackend,
|
||||
}
|
||||
|
||||
fn potential_cause(panic_info: &PanicInfo) -> Option<String> {
|
||||
let location = panic_info
|
||||
.location()
|
||||
.map_or("".to_string(), |x| x.file().to_string())
|
||||
.to_lowercase();
|
||||
|
||||
// Use some basic heuristics to determine the likely cause of the panic. This is
|
||||
// deliberately overly simplistic as the vast majority of graphics errors
|
||||
// for example are caused by an incompatible GPU rather than a bug.
|
||||
let potential_cause = if location.contains("gfx") || location.contains("wgpu") {
|
||||
Some(PotentialPanicCause::GraphicsCardIncompatibleWithRenderingBackend)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
potential_cause.map(potential_cause_to_string)
|
||||
}
|
||||
|
||||
fn potential_cause_to_string(potential_cause: PotentialPanicCause) -> String {
|
||||
match potential_cause {
|
||||
PotentialPanicCause::GraphicsCardIncompatibleWithRenderingBackend => {
|
||||
"This error occurs when your graphics card is not compatible with the selected \
|
||||
graphics mode. This can be changed in the Airshipper settings window, however it may \
|
||||
be the case that your graphics card is not supported by any graphics mode."
|
||||
.to_string()
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user