Fix T78285: Invalid thread safety in shrinkwrap modifier code.

This uses mesh's runtime mutex for both `BKE_mesh_runtime_looptri_ensure`
(was using its own global RW mutex before), and `BKE_mesh_wrapper_ensure_mdata`
(was not protected at all before).

This is more like a band-aid than a proper fix, as mentioned in the report
proper fix would be for the modifier to request those data (the relevant
BVHTree, which would implicitely also call the tow others) through flags,
just like it does for regular CDData layers. But this is a much bigger
refactor to be done outside of bugfix scope.

Reviewed By: sergey

Maniphest Tasks: T78285

Differential Revision: https://developer.blender.org/D8415
This commit is contained in:
Bastien Montagne 2020-07-29 17:36:27 +02:00 committed by Bastien Montagne
parent 54a2fcc0f3
commit 4e6975ffd6
Notes: blender-bot 2023-02-13 21:59:55 +01:00
Referenced by issue #78285, If object is reference for 2 shrinkwraps, entering it`s edit mode crashes Blender.
2 changed files with 15 additions and 11 deletions

View File

@ -43,8 +43,6 @@
/** \name Mesh Runtime Struct Utils
* \{ */
static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
/**
* Default values defined at read time.
*/
@ -159,23 +157,21 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh)
{
MLoopTri *looptri;
BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ);
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
looptri = mesh->runtime.looptris.array;
BLI_rw_mutex_unlock(&loops_cache_lock);
if (looptri != NULL) {
BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime.looptris.len);
}
else {
BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE);
/* We need to ensure array is still NULL inside mutex-protected code,
* some other thread might have already recomputed those looptris. */
if (mesh->runtime.looptris.array == NULL) {
BKE_mesh_runtime_looptri_recalc(mesh);
}
BKE_mesh_runtime_looptri_recalc(mesh);
looptri = mesh->runtime.looptris.array;
BLI_rw_mutex_unlock(&loops_cache_lock);
}
BLI_mutex_unlock(mesh_eval_mutex);
return looptri;
}

View File

@ -40,6 +40,7 @@
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_editmesh.h"
@ -96,9 +97,14 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
BLI_mutex_unlock(mesh_eval_mutex);
return;
}
const eMeshWrapperType geom_type_orig = me->runtime.wrapper_type;
me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
@ -130,6 +136,8 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
if (me->runtime.wrapper_type_finalize) {
BKE_mesh_wrapper_deferred_finalize(me, &me->runtime.cd_mask_extra);
}
BLI_mutex_unlock(mesh_eval_mutex);
}
bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])