[Bf-blender-cvs] [3212e72cfea] blender2.8: Depsgraph: Fix crash opening file with IK solver with copy on write enabled

Sergey Sharybin noreply at git.blender.org
Wed Jul 19 17:33:56 CEST 2017


Commit: 3212e72cfea2bbfdb8bbf765f0326b17e588bfb3
Author: Sergey Sharybin
Date:   Wed Jul 19 09:27:57 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB3212e72cfea2bbfdb8bbf765f0326b17e588bfb3

Depsgraph: Fix crash opening file with IK solver with copy on write enabled

The issue was caused by id_copy_no_main() changing pointers of constraints used
in pose to a newly allocated ID. This is correct, but caused confusion too our
copy on write remapping, because we are mimicing inplace duplication by copying
memory over from a temporarily duplicated ID to a proper placeholder. This was
causing dangling pointers in pose to a temporarily allocated ID.

Now we add special code to remapping callback which replaces temporary ID with
a proper one.

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

M	source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc

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

diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index df5dff73e67..44f3eeb21f0 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -289,16 +289,40 @@ Scene *scene_copy_no_main(Scene *scene)
 /* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
  * with the one created by CoW system.
  */
-int foreach_libblock_remap_callback(void *user_data,
+
+struct RemapCallbackUserData {
+	/* Dependency graph for which remapping is happening. */
+	const Depsgraph *depsgraph;
+	/* Temporarily allocated memory for copying purposes. This ID will
+	 * be discarded after expanding is done, so need to make sure temp_id
+	 * is replaced with proper real_id.
+	 *
+	 * NOTE: This is due to our logic of "inplace" duplication, where we
+	 * use generic duplication routines (which gives us new ID) which then
+	 * is followed with copying data to a placeholder we prepared before and
+	 * discarding pointer returned by duplication routines.
+	 */
+	const ID *temp_id;
+	ID *real_id;
+};
+
+int foreach_libblock_remap_callback(void *user_data_v,
                                     ID * /*id_self*/,
                                     ID **id_p,
                                     int /*cb_flag*/)
 {
-	Depsgraph *depsgraph = (Depsgraph *)user_data;
+	RemapCallbackUserData *user_data = (RemapCallbackUserData *)user_data_v;
+	const Depsgraph *depsgraph = user_data->depsgraph;
 	if (*id_p != NULL) {
 		const ID *id_orig = *id_p;
-		ID *id_cow = depsgraph->get_cow_id(id_orig);
-		if (id_cow != NULL) {
+		if (id_orig == user_data->temp_id) {
+			DEG_COW_PRINT("    Remapping datablock for %s: id_temp=%p id_cow=%p\n",
+			              id_orig->name, id_orig, id_cow);
+			*id_p = user_data->real_id;
+		}
+		else {
+			ID *id_cow = depsgraph->get_cow_id(id_orig);
+			BLI_assert(id_cow != NULL);
 			DEG_COW_PRINT("    Remapping datablock for %s: id_orig=%p id_cow=%p\n",
 			              id_orig->name, id_orig, id_cow);
 			*id_p = id_cow;
@@ -484,6 +508,11 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
 	 * - We don't want bmain's content to be freed when main is freed.
 	 */
 	bool done = false;
+	/* Need to make sure the possibly temporary allocated memory is correct for
+	 * until we are fully done with remapping original pointers with copied on
+	 * write ones.
+	 */
+	ID *newid = NULL;
 	/* First we handle special cases which are not covered by id_copy() yet.
 	 * or cases where we want to do something smarter than simple datablock
 	 * copy.
@@ -507,7 +536,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
 		}
 	}
 	if (!done) {
-		ID *newid;
 		if (id_copy_no_main(id_orig, &newid)) {
 			/* We copy contents of new ID to our CoW placeholder and free ID memory
 			 * returned by id_copy().
@@ -517,7 +545,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
 			 */
 			const size_t size = BKE_libblock_get_alloc_info(GS(newid->name), NULL);
 			memcpy(id_cow, newid, size);
-			MEM_freeN(newid);
 			done = true;
 		}
 	}
@@ -532,15 +559,23 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
 	ntree_hack_remap_pointers(depsgraph, id_cow);
 #endif
 
+	RemapCallbackUserData user_data;
+	user_data.depsgraph = depsgraph;
+	user_data.temp_id = newid;
+	user_data.real_id = id_cow;
 	BKE_library_foreach_ID_link(NULL,
 	                            id_cow,
 	                            foreach_libblock_remap_callback,
-	                            (void *)depsgraph,
+	                            (void *)&user_data,
 	                            IDWALK_NOP);
 	/* Correct or tweak some pointers which are not taken care by foreach
 	 * from above.
 	 */
 	update_special_pointers(depsgraph, id_orig, id_cow);
+	/* Now we can safely discard temporary memory used for copying. */
+	if (newid != NULL) {
+		MEM_freeN(newid);
+	}
 	return id_cow;
 }




More information about the Bf-blender-cvs mailing list