catch asset loader panics (#14809)
# Objective currently if an asset loader panics, the asset is left in a perpetual `Loading` state. this can occur with external crates (eg the image crate panics on bad data). catch this panic and resolve the asset to `Failed` ## Solution `AssertUnwindSafe(loader.load).catch_unwind()` and map the panic to an `AssetLoadError` separated out from #13170
This commit is contained in:
		
							parent
							
								
									80028d1323
								
							
						
					
					
						commit
						75738ed80f
					
				| @ -22,13 +22,13 @@ use bevy_tasks::IoTaskPool; | |||||||
| use bevy_utils::tracing::{error, info}; | use bevy_utils::tracing::{error, info}; | ||||||
| use bevy_utils::{CowArc, HashSet}; | use bevy_utils::{CowArc, HashSet}; | ||||||
| use crossbeam_channel::{Receiver, Sender}; | use crossbeam_channel::{Receiver, Sender}; | ||||||
| use futures_lite::StreamExt; | use futures_lite::{FutureExt, StreamExt}; | ||||||
| use info::*; | use info::*; | ||||||
| use loaders::*; | use loaders::*; | ||||||
| use parking_lot::RwLock; | use parking_lot::RwLock; | ||||||
| use std::future::Future; |  | ||||||
| use std::{any::Any, path::PathBuf}; | use std::{any::Any, path::PathBuf}; | ||||||
| use std::{any::TypeId, path::Path, sync::Arc}; | use std::{any::TypeId, path::Path, sync::Arc}; | ||||||
|  | use std::{future::Future, panic::AssertUnwindSafe}; | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| 
 | 
 | ||||||
| // Needed for doc string
 | // Needed for doc string
 | ||||||
| @ -1176,13 +1176,20 @@ impl AssetServer { | |||||||
|         let asset_path = asset_path.clone_owned(); |         let asset_path = asset_path.clone_owned(); | ||||||
|         let load_context = |         let load_context = | ||||||
|             LoadContext::new(self, asset_path.clone(), load_dependencies, populate_hashes); |             LoadContext::new(self, asset_path.clone(), load_dependencies, populate_hashes); | ||||||
|         loader.load(reader, meta, load_context).await.map_err(|e| { |         AssertUnwindSafe(loader.load(reader, meta, load_context)) | ||||||
|             AssetLoadError::AssetLoaderError(AssetLoaderError { |             .catch_unwind() | ||||||
|  |             .await | ||||||
|  |             .map_err(|_| AssetLoadError::AssetLoaderPanic { | ||||||
|                 path: asset_path.clone_owned(), |                 path: asset_path.clone_owned(), | ||||||
|                 loader_name: loader.type_name(), |                 loader_name: loader.type_name(), | ||||||
|                 error: e.into(), |             })? | ||||||
|  |             .map_err(|e| { | ||||||
|  |                 AssetLoadError::AssetLoaderError(AssetLoaderError { | ||||||
|  |                     path: asset_path.clone_owned(), | ||||||
|  |                     loader_name: loader.type_name(), | ||||||
|  |                     error: e.into(), | ||||||
|  |                 }) | ||||||
|             }) |             }) | ||||||
|         }) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1404,6 +1411,11 @@ pub enum AssetLoadError { | |||||||
|     CannotLoadProcessedAsset { path: AssetPath<'static> }, |     CannotLoadProcessedAsset { path: AssetPath<'static> }, | ||||||
|     #[error("Asset '{path}' is configured to be ignored. It cannot be loaded.")] |     #[error("Asset '{path}' is configured to be ignored. It cannot be loaded.")] | ||||||
|     CannotLoadIgnoredAsset { path: AssetPath<'static> }, |     CannotLoadIgnoredAsset { path: AssetPath<'static> }, | ||||||
|  |     #[error("Failed to load asset '{path}', asset loader '{loader_name}' panicked")] | ||||||
|  |     AssetLoaderPanic { | ||||||
|  |         path: AssetPath<'static>, | ||||||
|  |         loader_name: &'static str, | ||||||
|  |     }, | ||||||
|     #[error(transparent)] |     #[error(transparent)] | ||||||
|     AssetLoaderError(#[from] AssetLoaderError), |     AssetLoaderError(#[from] AssetLoaderError), | ||||||
|     #[error(transparent)] |     #[error(transparent)] | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 robtfm
						robtfm