summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-06-01 02:37:38 +0200
committerHampusM <hampus@hampusmat.com>2026-06-01 02:37:38 +0200
commit8d5668151c3efbb757c4421a9fe35e2c35cbd992 (patch)
treeefb0281c3e3a9956fae881bdf384893497d459e7
parentc0e661a7c9fa2ab9a2be3c26a3913523667e408f (diff)
fix(engine): stop if windowing app thread panics
-rw-r--r--engine/src/windowing.rs69
1 files 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<ArrayQueue<MessageFromApp>>,
message_to_app_queue: Arc<ArrayQueue<MessageToApp>>,
shared_state: Arc<SharedState>,
+ thread_panicked: Arc<AtomicBool>,
display_handle: Option<OwnedDisplayHandle>,
windows: MapVec<WindowId, (Arc<winit::window::Window>, 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<ArrayQueue<MessageFromApp>>,
+ message_to_app_queue_b: Arc<ArrayQueue<MessageToApp>>,
+ shared_state_b: Arc<SharedState>,
+)
+{
+ 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<EventLoop<()>, EventLoopError>
{
let mut event_loop_builder = EventLoop::builder();