From c0e661a7c9fa2ab9a2be3c26a3913523667e408f Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 1 Jun 2026 02:20:57 +0200 Subject: fix(engine): stop if asset import work queue thread panics --- engine/src/work_queue.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'engine/src/work_queue.rs') diff --git a/engine/src/work_queue.rs b/engine/src/work_queue.rs index a2b7db9..494d2b5 100644 --- a/engine/src/work_queue.rs +++ b/engine/src/work_queue.rs @@ -1,5 +1,8 @@ +use std::borrow::Cow; use std::marker::PhantomData; +use std::panic::catch_unwind; use std::sync::mpsc::{channel as mpsc_channel, Sender as MpscSender}; +use std::sync::{Arc, OnceLock}; use std::thread::{Builder as ThreadBuilder, JoinHandle as ThreadJoinHandle}; pub struct Work @@ -12,6 +15,7 @@ pub struct Work pub struct WorkQueue { work_sender: MpscSender>, + thread_panic: Arc>>, _thread: ThreadJoinHandle<()>, _pd: PhantomData, } @@ -22,15 +26,36 @@ impl WorkQueue { let (work_sender, work_receiver) = mpsc_channel::>(); + let thread_panic = Arc::new(OnceLock::new()); + + let thread_panic_b = thread_panic.clone(); + Self { work_sender, + thread_panic: thread_panic, _thread: ThreadBuilder::new() .name(name.to_string()) .spawn(move || { - let work_receiver = work_receiver; + if let Err(panic_err) = catch_unwind(|| { + while let Ok(work) = work_receiver.recv() { + (work.func)(work.user_data); + } + }) { + let panic_message: Cow<'static, str> = + if let Some(panic_message) = + panic_err.downcast_ref::<&'static str>() + { + (*panic_message).into() + } else if let Some(panic_message) = + panic_err.downcast_ref::() + { + panic_message.clone().into() + } else { + "(unknown panic payload type)".into() + }; - while let Ok(work) = work_receiver.recv() { - (work.func)(work.user_data); + let _ = thread_panic_b + .set(panic_message.into_owned().into_boxed_str()); } }) .expect("Failed to create work queue thread"), @@ -38,6 +63,11 @@ impl WorkQueue } } + pub fn get_thread_panic(&self) -> Option<&str> + { + self.thread_panic.get().map(|thread_panic| &**thread_panic) + } + pub fn add_work(&self, work: Work) { if self.work_sender.send(work).is_err() { -- cgit v1.2.3-18-g5258