Page MenuHome

bpy.ops.script.reload() seg fault
Closed, ResolvedPublic

Description

System Information
Operating system: Darwin-19.5.0-x86_64-i386-64bit 64 Bits
Graphics card: AMD Radeon Pro 5500M OpenGL Engine ATI Technologies Inc. 4.1 ATI-3.9.15

Blender Version
Broken: version: 2.91.0 Alpha, branch: master, commit date: 2020-08-11 20:18, hash: rBec5f39208785
Worked: (newest version of Blender that worked as expected)

Short description of error
Simply running bpy.ops.script.reload() causes a seg fault. Not always, but usually the second or third time I run it. I have tested with no unofficial addons installed.
Running F3 > Reload Scripts works fine.

terminal output:
Writing: /var/folders/9j/s986zj3575d_p6ns3hqf3sn00000gn/T/blender.crash.txt
[1] 58385 segmentation fault ./Blender

Exact steps for others to reproduce the error
open blender
run bpy.ops.script.reload() in the console

Event Timeline

Robert Guetzkow (rjg) changed the task status from Needs Triage to Confirmed.Fri, Sep 11, 12:38 PM
Robert Guetzkow (rjg) triaged this task as High priority.

The execution of CONSOLE_OT_execute results in a mangled data structure of the operator op after wm_operator_invoke calls rna_operator_execute_cb through retval = op->type->exec(C, op);. Subsequent access to the operator's data structure result in the crash.

Dalai Felinto (dfelinto) changed the task status from Confirmed to Needs Information from User.Fri, Sep 11, 4:21 PM
Dalai Felinto (dfelinto) lowered the priority of this task from High to Normal.

I cannot reproduce it in Linux with 2.83, 2.90 or master (2.91 to be).

Can either @Tomasz Dysinski (bunnybones) or @Robert Guetzkow (rjg) check what was the latest working version of Blender where this doesn't crash? Lowering the priority to normal until we figure this out. Specially since this only happens when running this via the console (not via the UI).

And @Robert Guetzkow (rjg) if you manage to crash in a debug build can you share the complete backtrace?

@Dalai Felinto (dfelinto) I will try to bisect this, probably on Sunday. Can't promise that I will have time to identify this though, in case it reaches far back. The stack trace is identical to the one in the supplied crash log, but I can add it as well.

Stack trace for build based on commit rBc01f8bb672f3 current master is equally affected:

WM_operator_py_idname(unsigned char * to, const unsigned char * from) Line 125	C
WM_operator_pystring_ex(bContext * C, wmOperator * op, const bool all_args, const bool macro_args, wmOperatorType * ot, PointerRNA * opptr) Line 246	C
WM_operator_pystring(bContext * C, wmOperator * op, const bool all_args, const bool macro_args) Line 308	C
wm_operator_reports(bContext * C, wmOperator * op, int retval, bool caller_owns_reports) Line 896	C
wm_operator_invoke(bContext * C, wmOperatorType * ot, wmEvent * event, PointerRNA * properties, ReportList * reports, const bool poll_only, bool use_last_properties) Line 1332	C
wm_handler_operator_call(bContext * C, ListBase * handlers, wmEventHandler * handler_base, wmEvent * event, PointerRNA * properties, const unsigned char * kmi_idname) Line 2132	C
wm_handlers_do_keymap_with_keymap_handler(bContext * C, wmEvent * event, ListBase * handlers, wmEventHandler_Keymap * handler, wmKeyMap * keymap, const bool do_debug_handler) Line 2442	C
wm_handlers_do_intern(bContext * C, wmEvent * event, ListBase * handlers) Line 2739	C
wm_handlers_do(bContext * C, wmEvent * event, ListBase * handlers) Line 2866	C
wm_event_do_handlers(bContext * C) Line 3364	C
WM_main(bContext * C) Line 485	C
main(int argc, const unsigned char * * UNUSED_argv_c) Line 531	C

2.82a, 2.81a, and 2.80rc3 also crash.

2.82a, 2.81a, and 2.80rc3 also crash.

It's possible to crash 2.79 as well. I think we can skip bisecting then.

This inspired a decent workaround, where I just run a script like this:

import bpy
bpy.ops.script.reload()

That way the reload function doesn't return anything to the console directly.
Thanks for the insight.

While there are multiple ways to fix this, many would mean making changes with bigger implications - just to support this one case, which I'm not so keen on.

  • Support operators being re-registered as part of operator execution complicates operator execution for a corner-case, will also cause hard to reason about bugs when an operators properties don't match those which they were activated in.
  • A quick fix for this case would be to move the console execution into a C operator, however it seems weak to change the implementation just to support reloading.

I think these are more reasonable alternatives...

  • Change bpy.ops.script.reload to postpone reloading so the operator that activates it can finish without being freed (this could use a timer for example).
  • Change bpy.ops.script.reload to inspect it's own call-stack. Skip reloading modules which are part of the call stack.

At the moment I'm more in favor of postponing reloading as it's not as involved as skipping modules in the call-stack, which might fail if there are any issues filtering out call-stack-modules could be tricky to do in a cross-platform way.

It's also possible the developer expects these modules to be reloaded, and needs to investigate why they don't.

@Campbell Barton (campbellbarton) - another option: change the poll on script.reload to return False when executing from the console editor.