[Bf-blender-cvs] [c626462] master: Fix T39209: Localizing materials could cause heisenbug with concurrent depsgraph updates.

Sergey Sharybin noreply at git.blender.org
Fri Mar 21 13:55:49 CET 2014


Commit: c626462c0fe1257c07948b49db1a41526682ba3f
Author: Sergey Sharybin
Date:   Fri Mar 21 13:44:38 2014 +0100
https://developer.blender.org/rBc626462c0fe1257c07948b49db1a41526682ba3f

Fix T39209: Localizing materials could cause heisenbug with concurrent
depsgraph updates.

Material datablocks were localized by first making a regular datablock
copy, which always gets inserted into the bmain list, and then removing
it again from bmain.

Problem is that this localization happens in preview threads, which can
run while the depsgraph is also updating GPU materials. In case the
copying of materials takes any amount of time, this can cause the
depsgraph call to material_changed to use an invalid, localized material
and access invalid GPUMaterial lists which have already been freed for
the actual material.

Solution is to not add localized datablocks to the bmain lists in the
first place. bmain should be totally immutable during preview or render
threads.

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

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/mask.c
M	source/blender/blenkernel/intern/material.c

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

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 5c92cc7..44a9885 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -49,6 +49,7 @@ struct PropertyRNA;
 
 void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_copy_nolib(struct ID *id) ATTR_NONNULL();
 void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void  BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
 
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 0bd1f97..f831378 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -808,6 +808,32 @@ void *BKE_libblock_copy_ex(Main *bmain, ID *id)
 	return idn;
 }
 
+void *BKE_libblock_copy_nolib(ID *id)
+{
+	ID *idn;
+	size_t idn_len;
+
+	idn = alloc_libblock_notest(GS(id->name));
+	assert(idn != NULL);
+
+	BLI_strncpy(idn->name, id->name, sizeof(idn->name));
+
+	idn_len = MEM_allocN_len(idn);
+	if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */
+		const char *cp = (const char *)id;
+		char *cpn = (char *)idn;
+
+		memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
+	}
+
+	id->newid = idn;
+	idn->flag |= LIB_NEW;
+
+	BKE_libblock_copy_data(idn, id, false);
+
+	return idn;
+}
+
 void *BKE_libblock_copy(ID *id)
 {
 	return BKE_libblock_copy_ex(G.main, id);
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 9b7886e..d08b731 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -734,6 +734,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
 	return mask;
 }
 
+/* TODO(sergey): Use generic BKE_libblock_copy_nolib() instead. */
 Mask *BKE_mask_copy_nolib(Mask *mask)
 {
 	Mask *mask_new;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 0dd62ae..eb8b385 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -256,8 +256,7 @@ Material *localize_material(Material *ma)
 	Material *man;
 	int a;
 	
-	man = BKE_libblock_copy(&ma->id);
-	BLI_remlink(&G.main->mat, man);
+	man = BKE_libblock_copy_nolib(&ma->id);
 
 	/* no increment for texture ID users, in previewrender.c it prevents decrement */
 	for (a = 0; a < MAX_MTEX; a++) {




More information about the Bf-blender-cvs mailing list