From e08db08a84bffaab27bc4562fd41f44756eb2e3e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 3 May 2014 15:58:37 +0200 Subject: Fix T39997: Multiple boolean modifiers sharing the same right operand crashes The issue was caused by the temporary CD layers being allocated for subsurf meshes, same as we've got back in 881fb43. In the long run this temporary storage is to be re-considered, but it'll also imply re-considering of the Derivedmesh interaction as well. For now let's use a simpler solution which is forbidding modifiers to call getArray for other objects' derivedMeshes but use an API calls which would allocate local copy of the data preventing race condition of shared data in DM. --- source/blender/blenkernel/intern/subsurf_ccg.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel/intern/subsurf_ccg.c') diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 16d21827f73..a9eba54128a 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -53,6 +53,7 @@ #include "BLI_edgehash.h" #include "BLI_math.h" #include "BLI_memarena.h" +#include "BLI_threads.h" #include "BKE_pbvh.h" #include "BKE_ccg.h" @@ -80,6 +81,9 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ +static ThreadRWMutex loops_cache_rwlock = BLI_RWLOCK_INITIALIZER; +static ThreadRWMutex origindex_cache_rwlock = BLI_RWLOCK_INITIALIZER; + static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int drawInteriorEdges, int useSubsurfUv, @@ -1326,16 +1330,21 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) /* DMFlagMat *faceFlags = ccgdm->faceFlags; */ /* UNUSED */ if (!ccgdm->ehash) { - MEdge *medge; + BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_WRITE); + if (!ccgdm->ehash) { + MEdge *medge; - ccgdm->ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); - medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); + ccgdm->ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); + medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); - for (i = 0; i < ccgdm->dm.numEdgeData; i++) { - BLI_edgehash_insert(ccgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i)); + for (i = 0; i < ccgdm->dm.numEdgeData; i++) { + BLI_edgehash_insert(ccgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i)); + } } + BLI_rw_mutex_unlock(&loops_cache_rwlock); } + BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_READ); totface = ccgSubSurf_getNumFaces(ss); mv = mloop; for (index = 0; index < totface; index++) { @@ -1378,6 +1387,7 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) } } } + BLI_rw_mutex_unlock(&loops_cache_rwlock); } static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly) @@ -2903,11 +2913,14 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type) int a, index, totnone, totorig; /* Avoid re-creation if the layer exists already */ + BLI_rw_mutex_lock(&origindex_cache_rwlock, THREAD_LOCK_READ); origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX); + BLI_rw_mutex_unlock(&origindex_cache_rwlock); if (origindex) { return origindex; } + BLI_rw_mutex_lock(&origindex_cache_rwlock, THREAD_LOCK_WRITE); DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX); @@ -2922,6 +2935,7 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type) CCGVert *v = ccgdm->vertMap[index].vert; origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v); } + BLI_rw_mutex_unlock(&origindex_cache_rwlock); return origindex; } -- cgit v1.2.3