From 8d5668151c3efbb757c4421a9fe35e2c35cbd992 Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 1 Jun 2026 02:37:38 +0200 Subject: fix(engine): stop if windowing app thread panics --- engine/src/windowing.rs | 69 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs index a0201db..bf29453 100644 --- a/engine/src/windowing.rs +++ b/engine/src/windowing.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::env::consts::EXE_SUFFIX; use std::hint::cold_path; +use std::panic::catch_unwind; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Weak}; use std::thread::Builder as ThreadBuilder; @@ -184,6 +185,7 @@ fn update_stuff( ref message_from_app_queue, ref mut display_handle, ref mut windows, + ref thread_panicked, .. } = *context; @@ -288,6 +290,11 @@ fn update_stuff( } } } + + if thread_panicked.load(Ordering::Relaxed) { + cold_path(); + actions.stop(); + } } fn handle_window_changed( @@ -344,6 +351,7 @@ pub struct Context message_from_app_queue: Arc>, message_to_app_queue: Arc>, shared_state: Arc, + thread_panicked: Arc, display_handle: Option, windows: MapVec, Uid)>, } @@ -420,28 +428,22 @@ impl Context let shared_state = Arc::new(SharedState::default()); let shared_state_b = shared_state.clone(); + let thread_panicked = Arc::new(AtomicBool::new(false)); + let thread_panicked_b = thread_panicked.clone(); + ThreadBuilder::new() .name("windowing app".to_string()) .spawn(move || { - let mut app = App { - message_from_app_queue: message_from_app_queue_b, - message_to_app_queue: message_to_app_queue_b, - shared_state: shared_state_b, - windows: MapVec::default(), - }; - - let event_loop = match create_event_loop() { - Ok(event_loop) => event_loop, - Err(err) => { - tracing::error!("Failed to create event loop: {err}"); - return; - } - }; - - event_loop.set_control_flow(EventLoopControlFlow::Poll); - - if let Err(err) = event_loop.run_app(&mut app) { - tracing::error!("Event loop error occurred: {err}"); + if catch_unwind(move || { + start_app( + message_from_app_queue_b, + message_to_app_queue_b, + shared_state_b, + ); + }) + .is_err() + { + thread_panicked_b.store(true, Ordering::Relaxed); } }) .expect("Failed to create windowing thread"); @@ -450,6 +452,7 @@ impl Context message_from_app_queue, message_to_app_queue, shared_state, + thread_panicked, display_handle: None, windows: MapVec::default(), } @@ -464,6 +467,34 @@ impl Drop for Context } } +fn start_app( + message_from_app_queue_b: Arc>, + message_to_app_queue_b: Arc>, + shared_state_b: Arc, +) +{ + let mut app = App { + message_from_app_queue: message_from_app_queue_b, + message_to_app_queue: message_to_app_queue_b, + shared_state: shared_state_b, + windows: MapVec::default(), + }; + + let event_loop = match create_event_loop() { + Ok(event_loop) => event_loop, + Err(err) => { + tracing::error!("Failed to create event loop: {err}"); + return; + } + }; + + event_loop.set_control_flow(EventLoopControlFlow::Poll); + + if let Err(err) = event_loop.run_app(&mut app) { + tracing::error!("Event loop error occurred: {err}"); + } +} + fn create_event_loop() -> Result, EventLoopError> { let mut event_loop_builder = EventLoop::builder(); -- cgit v1.2.3-18-g5258