From 8682ad1908eaa61b0d85437e0d7239a8add140b9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 27 Mar 2024 18:06:31 +0100 Subject: [PATCH] Fix: Memory leak and race condition with particle effector RNG Store RNG on per thread data, instead of the effector itself which may be used by multiple objects evaluated in different threads. This has been causing the blendfile_versioning test to fail randomly. Thanks Ray and Aras for helping track this down. Pull Request: https://projects.blender.org/blender/blender/pulls/119967 --- source/blender/blenkernel/BKE_effect.h | 4 ++++ source/blender/blenkernel/intern/effect.cc | 19 ++++++------------- source/blender/blenkernel/intern/object.cc | 3 --- source/blender/blenkernel/intern/particle.cc | 5 +---- .../blender/makesdna/DNA_object_force_types.h | 2 -- 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index ec47c55eec4..777deb59b3e 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -16,6 +16,7 @@ extern "C" { struct Collection; struct Depsgraph; struct ListBase; +struct RNG; struct Object; struct ParticleData; struct ParticleKey; @@ -78,6 +79,9 @@ typedef struct EffectorCache { struct PartDeflect *pd; + /** Random noise generator for e.g. wind. */ + struct RNG *rng; + /* precalculated for guides */ struct GuideEffectorData *guide_data; float guide_loc[4], guide_dir[3], guide_radius; diff --git a/source/blender/blenkernel/intern/effect.cc b/source/blender/blenkernel/intern/effect.cc index c95e29e5547..f20ca5c9056 100644 --- a/source/blender/blenkernel/intern/effect.cc +++ b/source/blender/blenkernel/intern/effect.cc @@ -113,9 +113,6 @@ PartDeflect *BKE_partdeflect_copy(const PartDeflect *pd_src) return nullptr; } PartDeflect *pd_dst = static_cast(MEM_dupallocN(pd_src)); - if (pd_dst->rng != nullptr) { - pd_dst->rng = BLI_rng_copy(pd_dst->rng); - } return pd_dst; } @@ -124,9 +121,6 @@ void BKE_partdeflect_free(PartDeflect *pd) if (!pd) { return; } - if (pd->rng) { - BLI_rng_free(pd->rng); - } MEM_freeN(pd); } @@ -136,12 +130,8 @@ static void precalculate_effector(Depsgraph *depsgraph, EffectorCache *eff) { float ctime = DEG_get_ctime(depsgraph); uint cfra = uint(ctime >= 0 ? ctime : -ctime); - if (!eff->pd->rng) { - eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra); - } - else { - BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); - } + + eff->rng = BLI_rng_new(eff->pd->seed + cfra); if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVES_LEGACY) { Curve *cu = static_cast(eff->ob->data); @@ -375,6 +365,9 @@ void BKE_effectors_free(ListBase *lb) { if (lb) { LISTBASE_FOREACH (EffectorCache *, eff, lb) { + if (eff->rng) { + BLI_rng_free(eff->rng); + } if (eff->guide_data) { MEM_freeN(eff->guide_data); } @@ -960,7 +953,7 @@ static void do_physical_effector(EffectorCache *eff, float *total_force) { PartDeflect *pd = eff->pd; - RNG *rng = pd->rng; + RNG *rng = eff->rng; float force[3] = {0, 0, 0}; float temp[3]; float fac; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 03899264a67..dd6834d90fc 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -245,9 +245,6 @@ static void object_copy_data(Main *bmain, if (ob_src->pd) { ob_dst->pd = (PartDeflect *)MEM_dupallocN(ob_src->pd); - if (ob_dst->pd->rng) { - ob_dst->pd->rng = (RNG *)MEM_dupallocN(ob_src->pd->rng); - } } BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata); diff --git a/source/blender/blenkernel/intern/particle.cc b/source/blender/blenkernel/intern/particle.cc index b608d908dd7..cae74c89b47 100644 --- a/source/blender/blenkernel/intern/particle.cc +++ b/source/blender/blenkernel/intern/particle.cc @@ -313,11 +313,8 @@ static void particle_settings_blend_write(BlendWriter *writer, ID *id, const voi } } -void BKE_particle_partdeflect_blend_read_data(BlendDataReader * /*reader*/, PartDeflect *pd) +void BKE_particle_partdeflect_blend_read_data(BlendDataReader * /*reader*/, PartDeflect * /*pd*/) { - if (pd) { - pd->rng = nullptr; - } } static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id) diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h index 71415d208b1..0d4829982c5 100644 --- a/source/blender/makesdna/DNA_object_force_types.h +++ b/source/blender/makesdna/DNA_object_force_types.h @@ -131,8 +131,6 @@ typedef struct PartDeflect { struct Tex *tex; /* effector noise */ - /** Random noise generator for e.g. wind. */ - struct RNG *rng; /** Noise of force. */ float f_noise; /** Noise random seed. */