From 71cdb55953c2a53546477716512e6d6af0687c23 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Tue, 8 Jul 2025 11:51:22 +0200 Subject: [PATCH] Fix #140562: Cycles crash with texture in custom camera with SVM on GPU After spending way too much time looking into the image handle code because I assumed the issue is some interaction between OSL code using a texture and the image system that's in SVM mode (which never happened before the custom camera) with printf debuggine because OptiX doesn't work in debug builds, it turns out the issue was something else entirely: C++ iterator bullshit. Specifically, when we remove an entry from services->textures, this invalidates the iterator, so the code restarts from the beginning. However, the for-loop still increments the iterator *before* checking the termination criterion. If we remove the only element of the map, we: - Set it = map.begin(), which equals map.end() since it's empty now - Increment it at the end of the loop iteration - Compare it == map.end(), which is wrong now since we're past the end No idea how this didn't blow up sooner, none of this seems camera-specific?? Anyways, the fix is simple - only increment if we didn't restart. Pull Request: https://projects.blender.org/blender/blender/pulls/141580 --- intern/cycles/scene/osl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index 05f374c7594..d1ffe2c1db2 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -286,7 +286,7 @@ void OSLManager::device_free(Device *device, DeviceScene * /*dscene*/, Scene *sc /* Remove any textures specific to an image manager from shared render services textures, since * the image manager may get destroyed next. */ foreach_render_services([scene](OSLRenderServices *services) { - for (auto it = services->textures.begin(); it != services->textures.end(); ++it) { + for (auto it = services->textures.begin(); it != services->textures.end();) { if (it->second.handle.get_manager() == scene->image_manager.get()) { /* Don't lock again, since the iterator already did so. */ services->textures.erase(it->first, false); @@ -294,6 +294,9 @@ void OSLManager::device_free(Device *device, DeviceScene * /*dscene*/, Scene *sc /* Iterator was invalidated, start from the beginning again. */ it = services->textures.begin(); } + else { + ++it; + } } }); }