Skip to content

Commit

Permalink
Fix AssetServer::get_asset_loader deadlock
Browse files Browse the repository at this point in the history
A thread could take the extension_to_loader_index read lock,
and then have the `server.loader` write lock taken in add_loader
before it can. Then add_loader can't take the extension_to_loader_index
lock, and the program deadlocks.

Fixed by descoping the extension_to_loader_index lock, since
get_asset_loader doesn't need to hold the lock for the duration,
just to get a copiable usize. The block might not be needed,
I think I could have gotten away with just inserting a `copied()`
call into the chain, but I wanted to make the reasoning clear for
future maintainers.
  • Loading branch information
vgel committed Jun 25, 2021
1 parent 3a1867a commit 5fb5a69
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,13 @@ impl AssetServer {
&self,
extension: &str,
) -> Result<Arc<Box<dyn AssetLoader>>, AssetServerError> {
self.server
.extension_to_loader_index
.read()
.get(extension)
.map(|index| self.server.loaders.read()[*index].clone())
let index = {
// scope map to drop lock as soon as possible
let map = self.server.extension_to_loader_index.read();
map.get(extension).copied()
};
index
.map(|index| self.server.loaders.read()[index].clone())
.ok_or_else(|| AssetServerError::MissingAssetLoader {
extensions: vec![extension.to_string()],
})
Expand Down

0 comments on commit 5fb5a69

Please sign in to comment.