Page MenuHome

Blender 2.81 - Crash when deleting scene from timers API
Closed, DuplicatePublic

Description

System Information
Operating system: Linux-5.0.0-32-generic-x86_64-with-debian-buster-sid 64 Bits
Graphics card: GeForce GTX 1070 Ti/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 435.21

Blender Version
Broken: version: 2.81 (sub 16), branch: master, commit date: 2019-11-06 20:48, hash: rB85637311c28f

Short description of error
Blender crashes if scene is deleted from timers API

Exact steps for others to reproduce the error

  1. Open blend file:

  1. Run script.
  2. Crash.

Event Timeline

Germano Cavalcante (mano-wii) lowered the priority of this task from 90 to Low.Nov 11 2019, 2:24 PM

I may be wrong, but I find it strange that CTX_wm_window(C) is NULL in this case.
Without getting into the real reason for the problem, this patch seems to solve the problem:

diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 2c42dba9131..23ceedd63d0 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -183,15 +183,15 @@ static void rna_Main_scenes_remove(
 
   if ((scene_new = scene->id.prev) || (scene_new = scene->id.next)) {
     if (do_unlink) {
-      wmWindow *win = CTX_wm_window(C);
+      Scene *scene_act = CTX_data_scene(C);
 
-      if (WM_window_get_active_scene(win) == scene) {
+      if (scene_act == scene) {
 
 #  ifdef WITH_PYTHON
         BPy_BEGIN_ALLOW_THREADS;
 #  endif
 
-        WM_window_set_active_scene(bmain, C, win, scene_new);
+        CTX_data_scene_set(C, scene_new);
 
 #  ifdef WITH_PYTHON
         BPy_END_ALLOW_THREADS;

But I will wait for a second opinion.

Note there are similar reports open T62074: 2.8: Python API: crash due to missing window context in Application timer, T71383: 2.8: Python API: window's workspace can't be set in Application timer.

Workaround [before the main issue id fixed] [next to the solution @Germano Cavalcante (mano-wii) provided] is to use an operator with a custom context:

import bpy

class TestOperator(bpy.types.Operator):
    bl_idname = "scene.test_operator"
    bl_label = "Test Operator"

    def execute(self, context):
        bpy.data.scenes.remove(context.scene)
        return {'FINISHED'}

bpy.utils.register_class(TestOperator)

def tick():
    window = bpy.context.window_manager.windows[0]
    ctx = {'window': window, 'screen': window.screen, 'scene': bpy.data.scenes['Scene.001']}  
    bpy.ops.scene.test_operator(ctx)
    
    return 5.0

bpy.app.timers.register(tick)

@Germano Cavalcante (mano-wii): think we should merge this into T62074? (since the underlying problem is really the same here...)
(next to your solution which seems good to have anyways? -- but would be sure on this one either...)