Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2017-07-19 10:27:57 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2017-07-19 16:20:06 +0300
commit3212e72cfea2bbfdb8bbf765f0326b17e588bfb3 (patch)
tree3a7ee7c58807cc3055d10a7726731d75b1d903a3 /source/blender/depsgraph
parentac136babb53d280744b107b873c65580315a13d6 (diff)
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.
Diffstat (limited to 'source/blender/depsgraph')
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc49
1 files changed, 42 insertions, 7 deletions
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;
}