Fix T47715: EXCEPTION_ACCESS_VIOLATION crash when removing modifiers or rendering
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 28 Apr 2016 10:29:42 +0000 (12:29 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 28 Apr 2016 10:32:59 +0000 (12:32 +0200)
The issue was caused by missing indirect dependencies from other scenes in the
current scene depsgraph, which was causing some threading conflicts.

Not sure what would be ideal solution here, for now use stupid but rather robust
approach to solve that. Maybe there's something better to do here tho.

source/blender/blenkernel/intern/depsgraph.c

index a029c8c7748d8fb90f46d944312fa9bdb249424c..14c230e4a451cdd5df0ef37970287f8baa868c75 100644 (file)
@@ -937,6 +937,8 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
        }
        dag->need_update = false;
 
+       BKE_main_id_tag_idcode(bmain, ID_OB, LIB_TAG_DOIT, false);
+
        /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
        BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
        BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
@@ -948,14 +950,43 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
        /* add current scene objects */
        for (base = sce->base.first; base; base = base->next) {
                ob = base->object;
-               
+               ob->id.tag |= LIB_TAG_DOIT;
                build_dag_object(dag, scenenode, bmain, sce, ob, mask);
                if (ob->proxy)
                        build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
                if (ob->dup_group) 
                        build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
        }
-       
+
+       /* There might be situations when object from current scene depends on
+        * objects form other scene AND objects from other scene has own
+        * dependencies on objects from other scene.
+        *
+        * This is really important to include such indirect dependencies in order
+        * to keep threaded update safe but since we don't really know if object is
+        * coming from current scene or another scene we do rather stupid tag-based
+        * check here: all the objects for which build_dag_object() was called are
+        * getting tagged with LIB_TAG_DOIT. This way if some node has untagged
+        * object we know it's an object from other scene.
+        *
+        * It should be enough to to it once, because if there's longer chain of
+        * indirect dependencies, all the new nodes will be added to the end of the
+        * list, meaning we'll keep covering them in this for loop.
+        */
+       for (node = sce->theDag->DagNode.first; node != NULL; node = node->next) {
+               if (node->type == ID_OB) {
+                       ob = node->ob;
+                       if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+                               ob->id.tag |= LIB_TAG_DOIT;
+                               build_dag_object(dag, scenenode, bmain, sce, ob, mask);
+                               if (ob->proxy)
+                                       build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
+                               if (ob->dup_group)
+                                       build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
+                       }
+               }
+       }
+
        BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
        
        /* Now all relations were built, but we need to solve 1 exceptional case;