diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-09-14 10:50:01 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-09-14 10:59:26 +0300 |
commit | 14b0f203744027451533f563c5d7373b73e070e0 (patch) | |
tree | f5190a031d6b52fdb2d07bdedef6ef652983a6ae /source/blender/editors/space_script | |
parent | c207f7c22e1439e0b285fba5d2c072bdae23f981 (diff) |
Fix T80694: Crash reloading scripts from the Python console
Running `bpy.ops.script.reload()` from Python was crashing
since the operator being called was it's self freed.
Change the reload operator to defer execution - as supporting
re-registration during execution is quite involved for a corner-case.
Diffstat (limited to 'source/blender/editors/space_script')
-rw-r--r-- | source/blender/editors/space_script/script_edit.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index f739bfe367e..56f99d31cf1 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -115,15 +115,32 @@ static int script_reload_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - WM_script_tag_reload(); - - /* TODO, this crashes on netrender and keying sets, need to look into why - * disable for now unless running in debug mode */ - WM_cursor_wait(1); - BPY_run_string_eval( - C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)"); - WM_cursor_wait(0); - WM_event_add_notifier(C, NC_WINDOW, NULL); + /* TODO(campbell): this crashes on netrender and keying sets, need to look into why + * disable for now unless running in debug mode. */ + + /* It would be nice if we could detect when this is called from the Python + * only postponing in that case, for now always do it. */ + if (true) { + /* Postpone when called from Python so this can be called from an operator + * that might be re-registered, crashing Blender when we try to read from the + * freed operator type which, see T80694. */ + BPY_run_string_exec(C, + (const char *[]){"bpy", NULL}, + "def fn():\n" + " bpy.utils.load_scripts(reload_scripts=True)\n" + " return None\n" + "bpy.app.timers.register(fn)"); + } + else { + WM_cursor_wait(true); + BPY_run_string_eval( + C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)"); + WM_cursor_wait(false); + } + + /* Note that #WM_script_tag_reload is called from `bpy.utils.load_scripts`, + * any additional updates required by this operator should go there. */ + return OPERATOR_FINISHED; #else UNUSED_VARS(C, op); |