Operating system: Ubuntu 18.04.4 LTS Linux-4.15.0-96-generic-x86_64-with-debian-buster-sid 64 Bits
Graphics card: Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2) Intel Open Source Technology Center 4.5 (Core Profile) Mesa 19.2.8
Broken: version: 2.90 (sub 3), branch: master, commit date: 2020-05-24 21:18, hash: rB5db2d9c82b7f
Also tested in blender 2.82a on same system, same problem, so it's been in since at least then.
Short description of error
Open the provided blend file, enable running of scripts, press ctrl-F12 to render the animation. After maybe doing some rendering, blender crashes with a segfault. (try a few times if render succeeds at first, crash is non deterministic)
Provided blend file uses cycles, render engine can also be set to eevee or workbench, problem still occurs.
The scene is updated on each frame change by a small python script. In a frame_change_post handler, the script looks for objects with a custom property called 'num' and updates the materials on any child with a name of the form Dot[1-10].<foo> such that one of them has the "on" material, and the others have the "off" material. This script runs fine with seeking through the animation in the timeline view, and doesn't cause the crash. This can be done with the viewport in any mode (rendered or shaded, or something else but the animation is only visible in rendered or shaded modes)
I'm ready to admit that there's a problem in my python script, but if there is, it's not obvious where it is, and it's not clear why it should work in the normal 3d viewport but not during render.
Regardless, It shouldn't be possible to segfault blender from a python script (without trying really hard). If this is not a bug in blender, but is a bug in the py script. then the condition for this segfault should be caught and an error message shown.
Exact steps for others to reproduce the error
- Open file
- Allow script execution
- Render animation
For reference, this is the script:
import bpy from copy import copy def handler(scene, deps): for obj in deps.objects: eval_obj = obj.evaluated_get(deps) if 'num' in eval_obj: sobj = scene.objects[eval_obj.name] for child in sobj.children: if child.name.startswith('Dot'): if len(child.material_slots) < 1: child.data.materials.append(bpy.data.materials.get('off')) if child.name.split('.').endswith(str(eval_obj['num'])): child.material_slots.material = bpy.data.materials.get('on') else: child.material_slots.material = bpy.data.materials.get('off') deps.update() def register(): bpy.app.handlers.frame_change_post.append(handler) def unregister(): for handler in copy(bpy.app.handlers.frame_change_post): if handler.__name__ == 'handler': bpy.app.handlers.frame_change_post.remove(handler) if __name__ == "__main__": unregister() register()