Fix crash in `egui_extras::FileLoader` after `forget_image` (#6995)

This pull request modifies the `BytesLoader` implementation for
`FileLoader` in `crates/egui_extras/src/loaders/file_loader.rs` to
improve thread safety and handle unexpected states more gracefully.

### Changes to thread safety and state handling:
* Updated the cache logic to check if the `uri` exists in the cache
before inserting the result. If the `uri` is not found, a log message is
added to indicate the loading was canceled. This change prevents
overwriting cache entries unexpectedly.

* Closes <https://github.com/emilk/egui/issues/6755>
* [x] I have followed the instructions in the PR template
This commit is contained in:
Nicolas 2025-06-27 11:27:03 +02:00 committed by GitHub
parent ae8363ddb5
commit ab9f55ab01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 4 deletions

View File

@ -3446,6 +3446,7 @@ impl Context {
/// Release all memory and textures related to the given image URI.
///
/// If you attempt to load the image again, it will be reloaded from scratch.
/// Also this cancels any ongoing loading of the image.
pub fn forget_image(&self, uri: &str) {
use load::BytesLoader as _;

View File

@ -95,10 +95,15 @@ impl BytesLoader for FileLoader {
}
Err(err) => Err(err.to_string()),
};
let prev = cache.lock().insert(uri.clone(), Poll::Ready(result));
assert!(matches!(prev, Some(Poll::Pending)), "unexpected state");
ctx.request_repaint();
log::trace!("finished loading {uri:?}");
let mut cache = cache.lock();
if let std::collections::hash_map::Entry::Occupied(mut entry) = cache.entry(uri.clone()) {
let entry = entry.get_mut();
*entry = Poll::Ready(result);
ctx.request_repaint();
log::trace!("finished loading {uri:?}");
} else {
log::trace!("cancelled loading {uri:?}\nNote: This can happen if `forget_image` is called while the image is still loading.");
}
}
})
.expect("failed to spawn thread");