mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 13:50:04 -04:00
Fix deadlock in ImageLoader, FileLoader, EhttpLoader (#7494)
* Recently CI runs started to hang randomly: https://github.com/emilk/egui/actions/runs/17427449210/job/49477714447?pr=7359 This fixes the deadlock and adds the basic deadlock detection we also added to Mutexes in #7468. Also, interestingly, the more sophisticated deadlock detection (behind the deadlock_detection feature) didn't catch this for some reason. I wonder why it exists in the first place, when parking_lot also has built in deadlock detection? It also seems to make tests slower, widget_tests usually needs ~30s, with the deadlock detection removed its only ~12s.
This commit is contained in:
@@ -100,15 +100,28 @@ impl ImageLoader for ImageCrateLoader {
|
||||
let result = crate::image::load_image_bytes(&bytes)
|
||||
.map(Arc::new)
|
||||
.map_err(|err| err.to_string());
|
||||
let mut cache = cache.lock();
|
||||
let repaint = {
|
||||
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);
|
||||
if let std::collections::hash_map::Entry::Occupied(mut entry) = cache.entry(uri.clone()) {
|
||||
let entry = entry.get_mut();
|
||||
*entry = Poll::Ready(result);
|
||||
log::trace!("ImageLoader - finished loading {uri:?}");
|
||||
true
|
||||
} else {
|
||||
log::trace!("ImageLoader - canceled loading {uri:?}\nNote: This can happen if `forget_image` is called while the image is still loading.");
|
||||
false
|
||||
}
|
||||
};
|
||||
// We may not lock Context while the cache lock is held, since this can
|
||||
// deadlock.
|
||||
// Example deadlock scenario:
|
||||
// - loader thread: lock cache
|
||||
// - main thread: lock ctx (e.g. in `Context::has_pending_images`)
|
||||
// - loader thread: try to lock ctx (in `request_repaint`)
|
||||
// - main thread: try to lock cache (from `Self::has_pending`)
|
||||
if repaint {
|
||||
ctx.request_repaint();
|
||||
log::trace!("ImageLoader - finished loading {uri:?}");
|
||||
} else {
|
||||
log::trace!("ImageLoader - canceled loading {uri:?}\nNote: This can happen if `forget_image` is called while the image is still loading.");
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user