Skip to content

Commit

Permalink
add logging for top-level crashes and fix window management (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
xTVaser authored Apr 1, 2023
1 parent 6b090ce commit 204bbff
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 83 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"svelte": "^3.58.0",
"svelte-preprocess": "^5.0.3",
"tailwindcss": "^3.2.7",
"typescript": "^4.9.5",
"typescript": "^5.0.3",
"vite": "^4.1.4"
},
"dependencies": {
Expand Down
22 changes: 22 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 17 additions & 15 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,28 @@ rust-version = "1.61"
tauri-build = { version = "1.2.1", features = [] }

[dependencies]
fs_extra = "1.3.0"
serde_json = "1.0.95"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2.4", features = ["api-all", "devtools", "reqwest-client"] }
zip-extract = "0.1.1"
zip = { version = "0.6.2" }
fern = { version = "0.6.1", features = ["date-based","colored"] }
backtrace = "0.3.67"
chrono = "0.4.23"
dir-diff = "0.3.2"
directories = "5.0.0"
fern = { version = "0.6.1", features = ["date-based","colored"] }
flate2 = "1.0.25"
fs_extra = "1.3.0"
futures-util = "0.3.26"
log = "0.4.17"
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
futures-util = "0.3.26"
sysinfo = "0.28.4"
wgpu = "0.15.1"
walkdir = "2.3.2"
dir-diff = "0.3.2"
thiserror = "1.0.40"
rev_buf_reader = "0.3.0"
flate2 = "1.0.25"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.95"
sysinfo = "0.28.4"
tar = "0.4.38"
tauri = { version = "1.2.4", features = ["api-all", "devtools", "reqwest-client"] }
thiserror = "1.0.40"
tokio = { version = "1", features = ["full"] }
walkdir = "2.3.2"
wgpu = "0.15.1"
zip = { version = "0.6.2" }
zip-extract = "0.1.1"

[features]
# by default Tauri runs in production mode
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub enum CommandError {
#[error("{0}")]
OSOperation(String),
#[error("{0}")]
WindowManagement(String),
#[error("{0}")]
BinaryExecution(String),
#[error("{0}")]
Support(String),
Expand Down
48 changes: 42 additions & 6 deletions src-tauri/src/commands/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,50 @@ use tauri::Manager;
use super::CommandError;

#[tauri::command]
pub async fn close_splashscreen(window: tauri::Window) {
pub async fn open_main_window(handle: tauri::AppHandle) -> Result<(), CommandError> {
// NOTE:
// When you create multiple static windows (inside the conf file)
// they are actually all running in the background
//
// This seemed to sometimes create a race condition where the app was not fully setup
// and when a panic hook was added that exited the process, the app would crash.
//
// So instead we make the main window at runtime, and close the splashscreen

// Create main window
// {
// "title": "OpenGOAL Launcher",
// "label": "main",
// "width": 800,
// "height": 600,
// "resizable": false,
// "fullscreen": false,
// "visible": false,
// "center": true,
// "decorations": false
// },
log::info!("Creating main window");
tauri::WindowBuilder::new(
&handle,
"main", /* the unique window label */
tauri::WindowUrl::App("index.html".parse().unwrap()),
)
.title("OpenGOAL Launcher")
.resizable(false)
.fullscreen(false)
.visible(true)
.center()
.decorations(false)
.build()
.map_err(|_| CommandError::WindowManagement(format!("Unable to create main launcher window")))?;
log::info!("Closing splash window");
// Close splashscreen
if let Some(splashscreen) = window.get_window("splashscreen") {
splashscreen.close().unwrap();
if let Some(splashscreen) = handle.app_handle().get_window("splashscreen") {
splashscreen
.close()
.map_err(|_| CommandError::WindowManagement(format!("Unable to close splash window")))?;
}
// Show main window
// TODO - cleanup this, return an error if we can't close it
window.get_window("main").unwrap().show().unwrap();
Ok(())
}

#[tauri::command]
Expand Down
107 changes: 80 additions & 27 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,57 @@
windows_subsystem = "windows"
)]

use directories::UserDirs;
use fern::colors::{Color, ColoredLevelConfig};
use tauri::{Manager, RunEvent};
use util::file::create_dir;

use std::env;
use backtrace::Backtrace;
use std::{env, io::Write};

mod commands;
mod config;
mod textures;
mod util;

fn log_crash(panic_info: Option<&std::panic::PanicInfo>, error: Option<tauri::Error>) {
let backtrace = Backtrace::new();
let log_contents;
if let Some(panic_info) = panic_info {
log_contents = format!("panic occurred: {:?}\n{:?}", panic_info, backtrace);
} else if let Some(error) = error {
log_contents = format!(
"unexpected app error occurred: {:?}\n{:?}",
error, backtrace
);
} else {
log_contents = format!("unexpected error occurred: {:?}", backtrace);
}
log::error!("{}", log_contents);
if let Some(user_dirs) = UserDirs::new() {
if let Some(desktop_dir) = user_dirs.desktop_dir() {
match std::fs::File::create(desktop_dir.join("og-launcher-crash.log")) {
Ok(mut file) => {
if let Err(err) = file.write_all(log_contents.as_bytes()) {
log::error!("unable to log crash report to a file - {:?}", err)
}
}
Err(err) => log::error!("unable to log crash report to a file - {:?}", err),
}
}
}
}

fn panic_hook(info: &std::panic::PanicInfo) {
log_crash(Some(info), None);
}

fn main() {
tauri::Builder::default()
// In the event that some catastrophic happens, atleast log it out
// the panic_hook will log to a file in the folder of the executable
std::panic::set_hook(Box::new(panic_hook));

let tauri_setup = tauri::Builder::default()
.setup(|app| {
// Setup Logging
let log_path = app
Expand All @@ -37,7 +75,7 @@ fn main() {
// since almost all of them are the same as the color for the whole line, we
// just clone `colors_line` and overwrite our changes
let colors_level = colors_line.clone().info(Color::Cyan);
fern::Dispatch::new()
let log_setup_ok = fern::Dispatch::new()
// Perform allocation-free log formatting
.format(move |out, message, record| {
out.finish(format_args!(
Expand All @@ -60,23 +98,26 @@ fn main() {
.chain(std::io::stdout())
.chain(fern::DateBased::new(&log_path, "/%Y-%m-%d.log"))
// Apply globally
.apply()
.expect("Could not setup logs");
log::info!("Logging Initialized");

// Truncate rotated log files to '5'
let mut paths: Vec<_> = std::fs::read_dir(&log_path)?.map(|r| r.unwrap()).collect();
paths.sort_by_key(|dir| dir.path());
paths.reverse();
let mut i = 0;
for path in paths {
i += 1;
log::info!("{}", path.path().display());
if i > 5 {
log::info!("deleting - {}", path.path().display());
std::fs::remove_file(path.path())?;
.apply();
match log_setup_ok {
Ok(_) => {
log::info!("Logging Initialized");
// Truncate rotated log files to '5'
let mut paths: Vec<_> = std::fs::read_dir(&log_path)?.map(|r| r.unwrap()).collect();
paths.sort_by_key(|dir| dir.path());
paths.reverse();
let mut i = 0;
for path in paths {
i += 1;
log::info!("{}", path.path().display());
if i > 5 {
log::info!("deleting - {}", path.path().display());
std::fs::remove_file(path.path())?;
}
}
}
}
Err(err) => log::error!("Could not initialize logging {:?}", err),
};

// Load the config (or initialize it with defaults)
//
Expand Down Expand Up @@ -120,15 +161,27 @@ fn main() {
commands::versions::remove_version,
commands::versions::go_to_version_folder,
commands::versions::list_downloaded_versions,
commands::window::close_splashscreen,
commands::window::open_main_window,
commands::window::open_dir_in_os
])
.build(tauri::generate_context!())
.expect("error building tauri app")
.run(|_app_handle, event| match event {
RunEvent::ExitRequested { .. } => {
std::process::exit(0);
}
_ => (),
})
.map_err(|err| {
log_crash(None, Some(err));
});
match tauri_setup {
Ok(app) => {
log::info!("application starting up");
app.run(|_app_handle, event| match event {
RunEvent::ExitRequested { .. } => {
log::info!("Exit requested, exiting!");
std::process::exit(0);
}
_ => (),
})
}
Err(err) => {
log::error!("Could not setup tauri application {:?}, exiting", err);
std::process::exit(1);
}
};
}
20 changes: 4 additions & 16 deletions src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": "",
"webviewInstallMode": {
"type": "embedBootstrapper"
}
"timestampUrl": ""
}
},
"allowlist": {
Expand All @@ -67,18 +64,9 @@
}
},
"windows": [
{
"title": "OpenGOAL Launcher",
"width": 800,
"height": 600,
"resizable": false,
"fullscreen": false,
"visible": false,
"center": true,
"decorations": false
},
{
"title": "OpenGOAL Launcher - Splash",
"label": "splashscreen",
"width": 200,
"height": 300,
"center": true,
Expand All @@ -87,8 +75,8 @@
"resizable": false,
"fullscreen": false,
"url": "./src/splash/index.html",
"label": "splashscreen",
"visible": true
"visible": true,
"focus": true
}
],
"security": {
Expand Down
9 changes: 2 additions & 7 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@
// Events
onMount(async () => {
// TODO - tauri doesn't seem to handle this event being unlistented to properly (go back to closing the window)
// - need to make an issue
// For now, we'll just handle all close events ourselves
await appWindow.listen("tauri://close-requested", async () => {
// TODO - confirm during an install
await appWindow.close();
});
// Temporary fix related to https://github.com/open-goal/launcher/issues/110
// TODO - this doesn't feel required anymore after i fixed the window switching
// but let's keep it for now because im paranoid about the issue cropping up again...
if (window.sessionStorage.getItem("refreshHack") !== "true") {
location.reload();
window.sessionStorage.setItem("refreshHack", "true");
Expand Down
6 changes: 3 additions & 3 deletions src/lib/rpc/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export async function openDir(directory: string): Promise<void> {
}
}

export async function closeSplashScreen(): Promise<boolean> {
export async function openMainWindow(): Promise<boolean> {
try {
invoke("close_splashscreen");
invoke("open_main_window");
return true;
} catch (e) {
exceptionLog(
"Unexpected error encountered when closing the splash screen",
"Unexpected error encountered when attempting to open the main window",
e
);
}
Expand Down
Loading

0 comments on commit 204bbff

Please sign in to comment.