Skip to content

Commit 75738ed

Browse files
authored
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
1 parent 80028d1 commit 75738ed

File tree

1 file changed

+18
-6
lines changed
  • crates/bevy_asset/src/server

1 file changed

+18
-6
lines changed

crates/bevy_asset/src/server/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ use bevy_tasks::IoTaskPool;
2222
use bevy_utils::tracing::{error, info};
2323
use bevy_utils::{CowArc, HashSet};
2424
use crossbeam_channel::{Receiver, Sender};
25-
use futures_lite::StreamExt;
25+
use futures_lite::{FutureExt, StreamExt};
2626
use info::*;
2727
use loaders::*;
2828
use parking_lot::RwLock;
29-
use std::future::Future;
3029
use std::{any::Any, path::PathBuf};
3130
use std::{any::TypeId, path::Path, sync::Arc};
31+
use std::{future::Future, panic::AssertUnwindSafe};
3232
use thiserror::Error;
3333

3434
// Needed for doc string
@@ -1176,13 +1176,20 @@ impl AssetServer {
11761176
let asset_path = asset_path.clone_owned();
11771177
let load_context =
11781178
LoadContext::new(self, asset_path.clone(), load_dependencies, populate_hashes);
1179-
loader.load(reader, meta, load_context).await.map_err(|e| {
1180-
AssetLoadError::AssetLoaderError(AssetLoaderError {
1179+
AssertUnwindSafe(loader.load(reader, meta, load_context))
1180+
.catch_unwind()
1181+
.await
1182+
.map_err(|_| AssetLoadError::AssetLoaderPanic {
11811183
path: asset_path.clone_owned(),
11821184
loader_name: loader.type_name(),
1183-
error: e.into(),
1185+
})?
1186+
.map_err(|e| {
1187+
AssetLoadError::AssetLoaderError(AssetLoaderError {
1188+
path: asset_path.clone_owned(),
1189+
loader_name: loader.type_name(),
1190+
error: e.into(),
1191+
})
11841192
})
1185-
})
11861193
}
11871194
}
11881195

@@ -1404,6 +1411,11 @@ pub enum AssetLoadError {
14041411
CannotLoadProcessedAsset { path: AssetPath<'static> },
14051412
#[error("Asset '{path}' is configured to be ignored. It cannot be loaded.")]
14061413
CannotLoadIgnoredAsset { path: AssetPath<'static> },
1414+
#[error("Failed to load asset '{path}', asset loader '{loader_name}' panicked")]
1415+
AssetLoaderPanic {
1416+
path: AssetPath<'static>,
1417+
loader_name: &'static str,
1418+
},
14071419
#[error(transparent)]
14081420
AssetLoaderError(#[from] AssetLoaderError),
14091421
#[error(transparent)]

0 commit comments

Comments
 (0)