Restore render depth counters after a caught panic

Fixes #3598

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-23 09:26:06 +07:00
committed by bflatastic
co-authored by Claude Haiku 5.5
parent 4cd20845e0
commit 2f620f8f31
2 changed files with 19 additions and 1 deletions
+1
View File
@@ -734,6 +734,7 @@ impl Renderer {
/// Start a frame: cache entries used from now on are marked with its stamp.
fn begin_frame(&mut self) {
self.stamp += 1;
self.inline_depth = 0;
}
/// End a frame: drop cache entries not used for a few frames (every render, thumbnails too,
+18 -1
View File
@@ -205,10 +205,18 @@ fn with_tile_renderer<T>(f: impl FnOnce(&mut Renderer) -> T) -> Option<T> {
}))
})?;
let mut r = r;
// Restores the depth even if `f` panics and the panic is caught (the renderer is then dropped).
struct Restore;
impl Drop for Restore {
fn drop(&mut self) {
CACHE.with(|c| c.borrow_mut().depth -= 1);
}
}
let guard = Restore;
let out = f(&mut r);
drop(guard);
CACHE.with(|c| {
let mut c = c.borrow_mut();
c.depth -= 1;
if c.renderer.is_none() {
c.renderer = Some(r);
}
@@ -687,4 +695,13 @@ mod tests {
assert_eq!(raster_scale(2.1, (10.0, 10.0)), raster_scale(3.9, (10.0, 10.0)));
assert!(raster_scale(64.0, (1000.0, 10.0)) * 1000.0 <= MAX_TILE_PX);
}
#[test]
fn tile_renderer_depth_survives_caught_panics() {
for _ in 0..4 {
let r = std::panic::catch_unwind(|| with_tile_renderer(|_| panic!("tile boom")));
assert!(r.is_err());
}
assert!(with_tile_renderer(|_| ()).is_some(), "depth leaked after caught panics");
}
}