From ab9f55ab0144462c1bc46a1fc49fe3b18f4d0fa7 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 27 Jun 2025 11:27:03 +0200 Subject: [PATCH] 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 * [x] I have followed the instructions in the PR template --- crates/egui/src/context.rs | 1 + crates/egui_extras/src/loaders/file_loader.rs | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 27a3fcd9..fb83a837 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -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 _; diff --git a/crates/egui_extras/src/loaders/file_loader.rs b/crates/egui_extras/src/loaders/file_loader.rs index 9feaebf5..d13134e2 100644 --- a/crates/egui_extras/src/loaders/file_loader.rs +++ b/crates/egui_extras/src/loaders/file_loader.rs @@ -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");