[Bf-blender-cvs] [956c539e597] master: Fix T89196: Depsgraph use-after-free after scene switching undo

Sergey Sharybin noreply at git.blender.org
Tue Jun 22 10:03:04 CEST 2021


Commit: 956c539e597aed84c355c8336dfd5797f4e69ea7
Author: Sergey Sharybin
Date:   Mon Jun 21 14:27:26 2021 +0200
Branches: master
https://developer.blender.org/rB956c539e597aed84c355c8336dfd5797f4e69ea7

Fix T89196: Depsgraph use-after-free after scene switching undo

Delay depsgraph visibility update tagging until it is known that
graph relations are up to date, and until it is known that the graph
is actually needed to be evaluated.

Differential Revision: https://developer.blender.org/D11660

===================================================================

M	source/blender/depsgraph/DEG_depsgraph.h
M	source/blender/depsgraph/intern/builder/pipeline.cc
M	source/blender/depsgraph/intern/depsgraph.cc
M	source/blender/depsgraph/intern/depsgraph.h
M	source/blender/depsgraph/intern/depsgraph_tag.cc
M	source/blender/depsgraph/intern/depsgraph_tag.h
M	source/blender/depsgraph/intern/eval/deg_eval.cc
M	source/blender/windowmanager/intern/wm_event_system.c

===================================================================

diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index d547c7cb440..27441c9a7ae 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -110,7 +110,7 @@ void DEG_free_node_types(void);
 /* Update Tagging -------------------------------- */
 
 /* Tag dependency graph for updates when visible scenes/layers changes. */
-void DEG_graph_tag_on_visible_update(struct Main *bmain, Depsgraph *depsgraph, const bool do_time);
+void DEG_graph_tag_on_visible_update(Depsgraph *depsgraph, const bool do_time);
 
 /* Tag all dependency graphs for update when visible scenes/layers changes. */
 void DEG_tag_on_visible_update(struct Main *bmain, const bool do_time);
diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc
index db0ad98f25a..28e4c973c1e 100644
--- a/source/blender/depsgraph/intern/builder/pipeline.cc
+++ b/source/blender/depsgraph/intern/builder/pipeline.cc
@@ -98,7 +98,7 @@ void AbstractBuilderPipeline::build_step_finalize()
   deg_graph_->scene_cow = (Scene *)deg_graph_->get_cow_id(&deg_graph_->scene->id);
   /* Flush visibility layer and re-schedule nodes for update. */
   deg_graph_build_finalize(bmain_, deg_graph_);
-  DEG_graph_tag_on_visible_update(bmain_, reinterpret_cast<::Depsgraph *>(deg_graph_), false);
+  DEG_graph_tag_on_visible_update(reinterpret_cast<::Depsgraph *>(deg_graph_), false);
 #if 0
   if (!DEG_debug_consistency_check(deg_graph_)) {
     printf("Consistency validation failed, ABORTING!\n");
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 8e1ab23fae0..6fe7d5f5d8b 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -62,6 +62,8 @@ namespace blender::deg {
 Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
     : time_source(nullptr),
       need_update(true),
+      need_visibility_update(true),
+      need_visibility_time_update(false),
       bmain(bmain),
       scene(scene),
       view_layer(view_layer),
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index b87ce94709a..ff536c19c05 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -108,6 +108,11 @@ struct Depsgraph {
   /* Indicates whether relations needs to be updated. */
   bool need_update;
 
+  /* Indicated whether IDs in this graph are to be tagged as if they first appear visible, with
+   * an optional tag for their animation (time) update. */
+  bool need_visibility_update;
+  bool need_visibility_time_update;
+
   /* Indicates which ID types were updated. */
   char id_type_updated[INDEX_ID_MAX];
 
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 24d333df1b0..78c5a0c7a13 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -500,8 +500,23 @@ void deg_graph_node_tag_zero(Main *bmain,
   deg_graph_id_tag_legacy_compat(bmain, graph, id, (IDRecalcFlag)0, update_source);
 }
 
-void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph, const bool do_time)
+void graph_tag_on_visible_update(Depsgraph *graph, const bool do_time)
 {
+  graph->need_visibility_update = true;
+  graph->need_visibility_time_update |= do_time;
+}
+
+} /* namespace */
+
+void graph_tag_ids_for_visible_update(Depsgraph *graph)
+{
+  if (!graph->need_visibility_update) {
+    return;
+  }
+
+  const bool do_time = graph->need_visibility_time_update;
+  Main *bmain = graph->bmain;
+
   /* NOTE: It is possible to have this function called with `do_time=false` first and later (prior
    * to evaluation though) with `do_time=true`. This means early output checks should be aware of
    * this. */
@@ -559,9 +574,10 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph, const bool do_ti
      * dependency graph. */
     id_node->previously_visible_components_mask = id_node->visible_components_mask;
   }
-}
 
-} /* namespace */
+  graph->need_visibility_update = false;
+  graph->need_visibility_time_update = false;
+}
 
 NodeType geometry_tag_to_component(const ID *id)
 {
@@ -804,16 +820,16 @@ void DEG_id_type_tag(Main *bmain, short id_type)
 }
 
 /* Update dependency graph when visible scenes/layers changes. */
-void DEG_graph_tag_on_visible_update(Main *bmain, Depsgraph *depsgraph, const bool do_time)
+void DEG_graph_tag_on_visible_update(Depsgraph *depsgraph, const bool do_time)
 {
   deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
-  deg::deg_graph_on_visible_update(bmain, graph, do_time);
+  deg::graph_tag_on_visible_update(graph, do_time);
 }
 
 void DEG_tag_on_visible_update(Main *bmain, const bool do_time)
 {
   for (deg::Depsgraph *depsgraph : deg::get_all_registered_graphs(bmain)) {
-    deg::deg_graph_on_visible_update(bmain, depsgraph, do_time);
+    deg::graph_tag_on_visible_update(depsgraph, do_time);
   }
 }
 
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.h b/source/blender/depsgraph/intern/depsgraph_tag.h
index 68b6a164be4..70504840fef 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.h
+++ b/source/blender/depsgraph/intern/depsgraph_tag.h
@@ -41,5 +41,9 @@ void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source);
 void graph_id_tag_update(
     Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source);
 
+/* Tag IDs of the graph for the visibility update tags.
+ * Will do nothing if the graph is not tagged for visibility update. */
+void graph_tag_ids_for_visible_update(Depsgraph *graph);
+
 }  // namespace deg
 }  // namespace blender
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 620e86550cc..6f35143e28f 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -45,6 +45,7 @@
 
 #include "intern/depsgraph.h"
 #include "intern/depsgraph_relation.h"
+#include "intern/depsgraph_tag.h"
 #include "intern/eval/deg_eval_copy_on_write.h"
 #include "intern/eval/deg_eval_flush.h"
 #include "intern/eval/deg_eval_stats.h"
@@ -365,6 +366,8 @@ static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state)
  */
 void deg_evaluate_on_refresh(Depsgraph *graph)
 {
+  graph_tag_ids_for_visible_update(graph);
+
   /* Nothing to update, early out. */
   if (graph->entry_tags.is_empty()) {
     return;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 7639f4a3d23..750b4e5e60d 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -380,10 +380,7 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file)
      */
     Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
     if (is_after_open_file) {
-      /* TODO(sergey): Remove after the handling of visibility tags is delayed until graph
-       * evaluation. */
-      DEG_graph_relations_update(depsgraph);
-      DEG_graph_tag_on_visible_update(bmain, depsgraph, true);
+      DEG_graph_tag_on_visible_update(depsgraph, true);
     }
     DEG_make_active(depsgraph);
     BKE_scene_graph_update_tagged(depsgraph, bmain);



More information about the Bf-blender-cvs mailing list