Blender Crashing Multiple Times a Minute

This has been going on for a week or two, but is only really bad when I’m constantly reloading scripts and then changing properties in the node editor. When I do that, it crashes up to multiple times per minute. It’s primarily “unhandled SIGBUS” and segmentation errors. The crash reports look like gibberish to me. I haven’t got the foggiest clue where to even begin since I currently have something like 7,500 lines of code including whitespace running.

"You should have stopped everything the moment Blender first crashed so you could find out what the problem was back then, when it was only a couple thousand lines." - You’re right.

It’s obviously 100% your fault because you only have .1% of the relevant knowledge concerning bpy and Python and you don’t even know how memory management works.” - That might be correct, but ChatGPT doesn’t know what’s going on either.

You have multiple thousands of lines of your own junior-dev code running, so it’s going to be impossible to find the bug if you don’t understand how the lower-level stuff works.” - I hope that’s not correct.

So my question for the forum is, what are some predictable ways an inexperienced person might accidentally crash Blender while Pythoning the node tree? Last time it was because I forgot to register an operator as undo. Here is an example of one of my nodes:

class EdgesNode(bpy.types.Node):
bl_idname = ‘edges_type’
bl_label = ‘Edges Node’
bl_icon = ‘SELECT_SET’
bl_width_default = 400

def init(self, context):
    return

def draw_buttons(self, context, layout):
    scene = context.scene
    column = layout.column(align=True)
    
    row = column.row()

    world = scene.world

    if world is not None and world.node_tree:
        node_tree = world.node_tree

        for controller in node_tree.nodes:

            # Check if the node is of the type 'group_controller_type'
            if controller.bl_idname == 'group_controller_type':
                row = column.row()
                row.prop(controller, "float_edge", slider=True, text=controller.str_group_label)

Are there any obvious, horrifying errors in that?

From your errors, I would guess you’re not registering and unregistering your classes

Additionally… here may be some hints (even if an older post)…

…also… there might be a bug in your code itslef which occasionally crashes blender ???

…maybe the evaluated changes lead to an error which you aren’t processign correctly ? Or can’t be evaluated (division by zero) ???

I am going to conclude that was most likely the cause, since I’ve had no crashes today after redoing my entire del section (thanks). I learned scripting on Blender 2.79 and in that context I developed a bad habit of just not adding the del’s since forgetting to do it never had an apparent negative impact on anything and I just did that at the very end when converting to proper add-on, especially since I didn’t realize that section would even run until it was an add-on. I’ve now learned that it apparently runs when you reload the script in Text Editor.

I’m guessing that there used to be logic that mitigated this crashing problem and it either no longer exists or has a bug in 4.0. It seems like missing one delete in the unregister should not crash Blender.

Thanks again!

1 Like

That wasn’t it. I spent most of yesterday redoing all my property registration/unregistration to use pointers and collection property things. I did all my objects that way and later found out that destroys self, so had to redo it. So I changed that back and just did scene. I found out the reason absolutely nothing was working anymore was because you have to change the way you access the properties, so instead of scene.[property] it becomes scene.[pointer property name].[property]. So that introduced at least 50 bugs throughout my codebase once I went through fixing everything, and I’m sure at least 12 still remain that I haven’t noticed yet since I’m still finding them.

But all that to quit having to have like 100 separate deletes in my unregister in reverse order. I was forcing ChatGPT to write them all because there was no way I was going to sit down and do all that by hand.

That seems to be all fixed now but Blender is still crashing regularly, although it doesn’t seem quite as bad anymore.

Only types that inherit from ID, Bone and PoseBone support custom properties in Blender so I’m not surprised accessing custom properties on Nodes crash Blender since you’re not supposed to :slight_smile:

https://docs.blender.org/api/current/bpy.props.html

Would you mind sharing the definition of your custom node group_controller_type ?

Screenshot 2024-03-08 at 12.57.52 PM

class GroupControllerNode(bpy.types.Node):
    bl_idname = 'group_controller_type'
    bl_label = 'Group Controller Node'
    bl_icon = 'STICKY_UVS_LOC'
    bl_width_default = 200
    
    # Assigned by group_info_updater on str_selected_light property.
    str_group_id: StringProperty(default="1")
    str_group_channels: StringProperty(default="")
    str_group_label: StringProperty(default="")
    
    # OSC argument templates for properties specific to the fixture type, not scene. For example, strobe, not intensity.
    str_enable_strobe_argument: StringProperty(default="# Strobe_Mode 127 Enter", description="Add # for group ID")
    str_disable_strobe_argument: StringProperty(default="# Strobe_Mode 76 Enter", description="Add # for group ID")
    str_enable_gobo_speed_argument: StringProperty(default="# Gobo_Mode 191 Enter", description="Add # for group ID")
    str_disable_gobo_speed_argument: StringProperty(default="# Gobo_Mode 63 Enter", description="Add # for group ID")
    str_gobo_id_argument: StringProperty(default="# Gobo_Select $ Enter", description="Add # for group ID and $ for value")
    str_gobo_speed_value_argument: StringProperty(default="# Gobo_Index/Speed at $ Enter", description="Add $ for animation data and # for fixture/group ID")
    str_enable_misc_effect_argument: StringProperty(default="# Gobo_Wheel_Mode 213 Enter", description="Add # for group ID")
    str_disable_misc_effect_argument: StringProperty(default="# Gobo_Wheel_Mode 213 Enter", description="Add # for group ID")
    str_enable_prism_argument: StringProperty(default="# Beam_Fx_Select 02 Enter", description="Add # for group ID")
    str_disable_prism_argument: StringProperty(default="# Beam_Fx_Select 01 Enter", description="Add # for group ID")
    
    # Min/max values mapped from 0-100 scale inside the harmonizer since we cannot live-update prop min/maxes. 
    # This provides user full use of the slider at all times.
    pan_min: bpy.props.IntProperty(default=-270, description="Minimum value for pan")
    pan_max: bpy.props.IntProperty(default=270, description="Maximum value for pan")
    tilt_min: bpy.props.IntProperty(default=-135, description="Minimum value for tilt")
    tilt_max: bpy.props.IntProperty(default=135, description="Maximum value for tilt")
    strobe_min: bpy.props.IntProperty(default=0, description="Minimum value for strobe")
    strobe_max: bpy.props.IntProperty(default=10, description="Maximum value for strobe")
    zoom_min: bpy.props.IntProperty(default=1, description="Minimum value for zoom")
    zoom_max: bpy.props.IntProperty(default=100, description="Maximum value for zoom")   
    iris_min: bpy.props.IntProperty(default=0, description="Minimum value for iris")
    iris_max: bpy.props.IntProperty(default=100, description="Maximum value for iris")  
    edge_min: bpy.props.IntProperty(default=0, description="Minimum value for edge")
    edge_max: bpy.props.IntProperty(default=100, description="Maximum value for edge")  
    speed_min: bpy.props.IntProperty(default=-200, description="Minimum value for speed")
    speed_max: bpy.props.IntProperty(default=200, description="Maximum value for speed")
    changer_speed_min: IntProperty(default=0, description="Minimum value for changer speed")
    changer_speed_max: IntProperty(default=0, description="Maximum value for changer speed")

    # Selected group and color profile enumerators.
    str_selected_light: EnumProperty(
        name="Selected Light",
        description="Choose a light object",
        items=lamp_objects,
        update=group_info_updater
    )
    color_profile_enum: EnumProperty(
        name="Color Profile",
        description="Choose a color profile for the group",
        items=color_profiles,
    )
    
    # User-accessible property definitions.
    influence: IntProperty(default=1, min=1, max=10, description="How many votes this controller has when there are conflicts", options={'ANIMATABLE'})
    float_intensity: FloatProperty(default=0, min=0, max=100, description="Intensity value", options={'ANIMATABLE'}, update=group_intensity_updater)
    float_vec_color: FloatVectorProperty(
        name="",
        subtype='COLOR',
        size=3,
        default=(1.0, 1.0, 1.0),
        min=0.0,
        max=1.0,
        description="Color value",
        update=group_color_updater
    )
    float_diffusion: FloatProperty(default=0, min=0, max=100, description="Diffusion value", options={'ANIMATABLE'}, update=group_diffusion_updater)
    float_pan: bpy.props.FloatProperty(default=0, min=-100, max=100, description="Pan value", options={'ANIMATABLE'}, update=group_pan_updater)
    float_tilt: FloatProperty(default=0, min=-100, max=100, description="Tilt value", options={'ANIMATABLE'}, update=group_tilt_updater)
    float_strobe: FloatProperty(default=0, min=0, max=100, description="Strobe value", options={'ANIMATABLE'}, update=group_strobe_updater)
    float_zoom: FloatProperty(default=0, min=0, max=100, description="Zoom value", options={'ANIMATABLE'}, update=group_zoom_updater)
    float_iris: FloatProperty(default=0, min=0, max=100, description="Iris value", options={'ANIMATABLE'}, update=group_iris_updater)
    float_edge: FloatProperty(default=0, min=0, max=100, description="Edge value", options={'ANIMATABLE'}, update=group_edge_updater)
    int_gobo_id: IntProperty(default=1, min=0, max=20, description="Gobo selection", options={'ANIMATABLE'}, update=group_gobo_id_updater)
    float_gobo_speed: FloatProperty(default=0, min=-100, max=100, description="Rotation of individual gobo speed", options={'ANIMATABLE'}, update=group_speed_updater)
    float_disc_speed: FloatProperty(default=0, min=-100, max=100, description="Rotation of gobo disc/wheel speed", options={'ANIMATABLE'})
    int_prism: IntProperty(default=0, min=0, max=1, description="Prism value. 1 is on, 0 is off", options={'ANIMATABLE'}, update=group_prism_updater)
    
    # Checkers for aborting redundant updates from frame_change_pre handler.
    float_influence_checker: FloatProperty(default=0, description="How much influence this controller has", options={'ANIMATABLE'})
    float_intensity_checker: FloatProperty(default=0, min=0, max=100, description="Intensity value", options={'ANIMATABLE'})
    float_vec_color_checker: FloatVectorProperty(name="", subtype='COLOR', size=3, default=(1.0, 1.0, 1.0))
    float_pan_checker: FloatProperty(default=0,)
    float_tilt_checker: FloatProperty(default=0)
    float_diffusion_checker: FloatProperty(default=0)
    float_strobe_checker: FloatProperty(default=0)
    float_zoom_checker: FloatProperty(default=0)
    float_iris_checker: FloatProperty(default=0)
    float_edge_checker: FloatProperty(default=0)
    gobo_id_checker: FloatProperty(default=0)
    float_speed_checker: FloatProperty(default=0)
    prism_checker: FloatProperty(default=0)    
    
    # Fan Center effect booleans.
    use_fan_center_intensity: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_tilt: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_pan: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_diffusion: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_strobe: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_zoom: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_iris: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_edge: BoolProperty(default=False, description="Use Fan Center effect")
    use_fan_center_speed: BoolProperty(default=False, description="Use Fan Center effect")
    
    # Toggles for turning off visibility to unneeded parameters.
    influence_is_on: BoolProperty(default=False, description="Influence is enabled when checked")
    intensity_is_on: BoolProperty(default=False, description="Intensity is enabled when checked")
    pan_tilt_is_on: BoolProperty(default=False, description="Pan/Tilt is enabled when checked")    
    color_is_on: BoolProperty(default=False, description="Color is enabled when checked")
    diffusion_is_on: BoolProperty(default=False, description="Diffusion is enabled when checked")
    strobe_is_on: BoolProperty(default=False, description="Strobe is enabled when checked")
    zoom_is_on: BoolProperty(default=False, description="Zoom is enabled when checked")
    iris_is_on: BoolProperty(default=False, description="Iris is enabled when checked")
    edge_is_on: BoolProperty(default=False, description="Edge is enabled when checked")
    gobo_id_is_on: BoolProperty(default=False, description="Gobo ID is enabled when checked")
    prism_is_on: BoolProperty(default=False, description="Prism is enabled when checked")
    
    def init(self, context):
        self.inputs.new('GroupInputType', "Driver Input")
        self.inputs.new('GroupInputType', "Driver Input")
        self.outputs.new('FlashOutType', "Flash")
        return

    def draw_buttons(self, context, layout):
        if self.influence_is_on:
            row = layout.row(align=True)
            row.prop(self, "influence", slider=True, text="Influence:")
            layout.separator()

        # This was originally added to avoid using depsgraph_update handler to reduce traffic, may be cut from final.
        active_influencer = bpy.data.objects.get(self.str_selected_light)
        if active_influencer is not None and active_influencer.select_get() and active_influencer.type == 'MESH':
            if active_influencer.is_influencer:
                row = layout.row()
                row.label(text="Influencer Location:")
                row = layout.row(align=True)
                row.prop(self, "influencer_x_location", toggle=True, text="X")
                row = layout.row(align=True)
                row.prop(self, "influencer_y_location", toggle=True, text="Y")
                row = layout.row(align=True)
                row.prop(self, "influencer_z_location", toggle=True, text="Z")
                layout.separator()
                layout.separator()

        row = layout.row(align=True)
        ## Use of row.alert logic here is probably redundant per existing Blender UI rules
        if not self.str_selected_light:
            row.alert = 1
        row.prop(self, "str_selected_light", text="", icon_only=True, icon='LIGHT')
        row.alert = 0
        
        # Must send identity info to some operators since buttons can be pressed on non-active nodes
        op_home = row.operator("node.home_group", icon='HOME', text="")
        op_home.node_name = self.name
        op_update = row.operator("node.update_group", icon='FILE_REFRESH', text="")
        op_update.node_name = self.name
        
        row.prop(self, "float_intensity", slider=True, text="Intensity:")
        
        # All strobe controls on a button/popup to avoid putting it on its own row.
        if self.strobe_is_on:
            row_one = row.column(align=True)
            row_one.scale_x = 1
            op = row_one.operator("my.view_strobe_props", icon='OUTLINER_OB_LIGHTPROBE', text="")
            op.node_name = self.name
    
        if self.color_is_on:
            sub = row.column(align=True)
            sub.scale_x = 0.3
            sub.prop(self, "float_vec_color", text="")
            sub_two = row.column(align=True)
            # Do not allow students/volunteers to mess up the color profile setting.
            if not context.scene.scene_props.school_mode_enabled:
                sub_two.scale_x = 0.8
                sub_two.prop(self, "color_profile_enum", text="", icon='COLOR', icon_only=True)

        if self.pan_tilt_is_on:
            row = layout.row(align=True)
            op = row.operator("my.view_pan_tilt_props", icon='ORIENTATION_GIMBAL', text="")
            op.node_name = self.name
            ## Need to switch to the blue color, not the red.
            if self.use_fan_center_pan:
                row.alert = 1
            row.prop(self, "use_fan_center_pan", text="", icon='PARTICLES')
            row.alert = 0
            row.prop(self, "float_pan", text="Pan", slider=True)
            if self.use_fan_center_tilt:
                row.alert = 1
            row.prop(self, "use_fan_center_tilt", text="", icon='PARTICLES')
            row.alert = 0
            row.prop(self, "float_tilt", text="Tilt", slider=True)
        
        if self.zoom_is_on or self.iris_is_on:
            row = layout.row(align=True)
            op = row.operator("my.view_zoom_iris_props", text="", icon='LINCURVE')
            op.node_name = self.name
            
            if self.zoom_is_on:
                if self.use_fan_center_zoom:
                    row.alert = 1
                row.prop(self, "use_fan_center_zoom", text="", icon='PARTICLES')
                row.alert = 0
                row.prop(self, "float_zoom", slider=True, text="Zoom:")
            if self.iris_is_on:
                if self.use_fan_center_iris:
                    row.alert = 1
                row.prop(self, "use_fan_center_iris", text="", icon='PARTICLES')
                row.alert = 0
                row.prop(self, "float_iris", slider=True, text="Iris:")
        
        if self.edge_is_on or self.diffusion_is_on:
            row = layout.row(align=True)
            op = row.operator("my.view_edge_diffusion_props", text="", icon='SELECT_SET')
            op.node_name = self.name
            
            if self.edge_is_on:
                if self.use_fan_center_zoom:
                    row.alert = 1
                row.prop(self, "use_fan_center_edge", text="", icon='PARTICLES')
                row.alert = 0
                row.prop(self, "float_edge", slider=True, text="Edge:")
            if self.diffusion_is_on:
                if self.use_fan_center_diffusion:
                    row.alert = 1
                row.prop(self, "use_fan_center_diffusion", text="", icon='PARTICLES')
                row.alert = 0
                row.prop(self, "float_diffusion", slider=True, text="Diffusion:")
        
        if self.gobo_id_is_on:
            row = layout.row(align=True)
            op = row.operator("my.view_gobo_props", text="", icon='POINTCLOUD_DATA')
            op.node_name = self.name
            
            row.prop(self, "int_gobo_id", text="Gobo:")
            row.prop(self, "float_gobo_speed", slider=True, text="Speed:")
            row.prop(self, "int_prism", slider=True, text="Prism:")

I’ve narrowed down the crashing issue to the script that comes from (currently at about 3,000 lines total out of a ~20,000 line project). I think it has something to do with my really elaborate “harmonizer” system. It’s there to harmonize conflicting control requests from multiple different controllers trying to control the same lighting fixture differently. Any parameter change might be handled by 10-15 different functions before it gets out of Blender. I’m going to be working on massively simplifying that system even though getting that system to work in the first place was a massive victory earlier in the project. But it needs to be simpler and smarter, and something about it is crashing Blender. My hope is I just need to rephrase one line or one type of line somewhere.

I just learned about “Fake Users”, which appears to be a deterrent against unwanted garbage collection. It makes me wonder if Blender is crashing because it sees all these nodes that don’t have any noodles, so it thinks it’s safe to delete the data behind the nodes. I then try to manipulate one of the node properties, but the underlying data has been deleted by garbage collection, so the OS terminates Blender since it’s trying to access memory that no longer belongs to Blender (i.e., Blender crashes).

That is one of my theories because the stuff runs correctly. It operates exactly as intended. It does what it’s supposed to. There are no error messages printed to Terminal. It just crashes sometimes after I try to manipulate node data. It seems like if I have this horrifying bug on my end deserving of repeated crashes, the code would not work. But the code works without printing errors. So it makes me think this may be a garbage collection issue. Nodes are intended to have noodles, they aren’t intended to be standalone island controllers. So Blender thinks it safe to delete their data.

So this makes me think maybe I should try setting all my nodes to Fake User and see if that stops the crashes.

This is further supported by the fact that the nodes I have been working on for the last few days all have noodles, and I have had zero crashes. There’s a case to be made that there is a correlation between noodleless nodes and crashes.

1 Like

Just in case you haven’t seen it, there’s a list of common causes of crashes in the Gotchas section of the API, and I noticed that your node has a couple of EnumProperties being populated by callback functions, and there is a known bug that causes crashes related to EnumProperties not storing their references:

Warning

There is a known bug with using a callback, Python must keep a reference to the strings returned by the callback or Blender will misbehave or even crash.

You can get around it by storing the data in a global variable.

1 Like

You can read more about the enum prop bug and possible alternative solutions to global variables there https://blender.stackexchange.com/questions/216230/is-there-a-workaround-for-the-known-bug-in-dynamic-enumproperty

Re your concerns about the fake user and garbage collection, I don’t think that’s it because when you add a node to a node tree, a relationship is automatically created between the node tree and the node (you can check that in the data API option of the outliner), and nodes don’t have a concept of users because they either don’t exist or they exist but they can only be part of the nodes of a single node tree. Since the compositor node tree is used by the scene, it won’t be garbage collected nor the node you placed, the number of links to other nodes is irrelevant. I have been using the python API for some years now and I don’t think I have once had to actively mess with the garbage collector. I’m almost certain the problem lies elsewhere.

I’m sorry to say that I think you’re pushing the limits of the API a little too far beyond it’s intended purpose. The very purpose of visual coding with nodes is to use nodes as buildings blocks and links as relationships between these blocks, here you’re basically recreating a panel interface inside a node which IMO is adding a responsibility to the node which it shouldn’t have. Ideally you would transform all of these settings into inputs and tweak the values inside the input fields. Or put all of these settings in the N panel of the compositor node tree so they’re not stored on a data block that is not designed to store this kind of data. The reason why no vanilla Blender node looks like the picture you posted, is because they’re not intended to be used like this by the devs. Just my 2 cents :slight_smile:

to clarify I’m not implying what you’re doing is wrong, just that it’s not suprising that it’s crashing a lot because you’re threading a little far from what the API was intended to do. For all intents and purposes if your addon works and gives you satisfying results, all good. You’re asking questions on here so I think I can offer some guidance and you’re prepared for constructive criticism, if you think my feedback doesn’t help you feel free to disregard, I will stop bothering you :wink:

1 Like

If Blender is about freedom to create, then I am using it exactly how it was intended to be used. I want to be able to sit in a dark room, listen to a song on repeat for an hour, imagine a fantastical lighting show for the song, and then create it—without any software restrictions. I can’t, not with even the best, most sophisticated lighting consoles. With the stuff I’m developing on top of Blender, I can. There are no restrictions to creativity.

Not using proper sockets with numerical values atm because they are very disagreeable to work with. Can’t easily add min/max, updaters, view toggles, sliders, in-line operators, etc. Instead I’m using label-only sockets as “pointers” for the traditional properties.

Using nodes in the first place because using the node GUI system is vehemently more pleasant to work with than any other GUI system for this type of need. It’s simply magical.

Will review/correct enumerator issue.

You can set up your own software with a node interface without the baggage of Blender - PyQt has very simple node tools, as does DearPyGui

re: what the API was intended to do - at least from what I can see the code posted uses properties in the same way that the Custom Nodes template uses them on Nodes, NodeSockets and NodeInterfaceSockets, which seems like an implicit indication from the devs that storing properties on those items is ok.

From the Custom Nodes template:

# Derived from the Node base type.
class MyCustomNode(MyCustomTreeNode, Node):
...
    # === Custom Properties ===
    # These work just like custom properties in ID data blocks
    # Extensive information can be found under
    # https://docs.blender.org/api/current/bpy.props.html
    my_string_prop: bpy.props.StringProperty()
    my_float_prop: bpy.props.FloatProperty(default=3.1415926)

Unless I’m misunderstanding what you meant.

1 Like

I love the baggage of Blender.

1 Like

Ah yes you’re right. Thank you for pointing it out. I would advise against using complex callbacks on these properties though, seeing as this part of the API is barely documented it would not surprise me that it leads to bugs.

What I mean is be careful with the side effects when you use an update callback on a property, re the warning in the docs

Typically, these callbacks should not affect any other data that the one owned by their data-block. When accessing external non-Blender data, thread safety mechanisms should be considered.

2 Likes

That’s fair, I’ve been caught by the callback bug before, and given the number of warnings on the Properties page of the API, I’m with you in assuming that the crash is a result of a prop callback. :slightly_smiling_face:

1 Like