Separate context freeing from task freeing in threaded particle updates
authorLukas Tönne <lukas.toenne@gmail.com>
Thu, 8 Jan 2015 11:40:27 +0000 (12:40 +0100)
committerLukas Tönne <lukas.toenne@gmail.com>
Tue, 20 Jan 2015 08:30:09 +0000 (09:30 +0100)
to prevent double-freeing/invalid mem access.

This can happen with the "virtual parents" feature, which generates both
parent and child paths. Each task free function also freed the shared
context, leading to double freeing.

source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_distribute.c
source/blender/blenkernel/intern/particle_system.c

index 718051609277d3203af7b372ea11e0713142f953..4c6b0cc0dacde7a11bc5ae948faddd3dee15d2f5 100644 (file)
@@ -350,6 +350,7 @@ void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct Pa
                                    struct ParticleCacheKey *cache, float mat[4][4], float *scale);
 
 void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim);
+void psys_thread_context_free(struct ParticleThreadContext *ctx);
 void psys_tasks_create(struct ParticleThreadContext *ctx, int totpart, struct ParticleTask **r_tasks, int *r_numtasks);
 void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
 
index aa62b7778c9b7e4e81bf40fb16ff0f2f0c870c3b..847cae9f0fc99c3b7e027459b4e0d7063448211b 100644 (file)
@@ -2587,6 +2587,8 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd
        
        psys_tasks_free(tasks_parent, numtasks_parent);
        psys_tasks_free(tasks_child, numtasks_child);
+       
+       psys_thread_context_free(&ctx);
 }
 
 /* figure out incremental rotations along path starting from unit quat */
index 90338e96945df7e0622d730701c0d0edd1c5e918..7a422abae474de4ab4ec7a632fbde242cb77574d 100644 (file)
@@ -1140,6 +1140,8 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
                ctx.dm->release(ctx.dm);
        
        psys_tasks_free(tasks, numtasks);
+       
+       psys_thread_context_free(&ctx);
 }
 
 /* ready for future use, to emit particles without geometry */
index 93eb273fc006dab417980a04a6372cd4ae712153..6e7e341e1cc18a9f24ca3ae9175c05532e7e7d17 100644 (file)
@@ -471,13 +471,24 @@ void psys_tasks_create(ParticleThreadContext *ctx, int totpart, ParticleTask **r
 
 void psys_tasks_free(ParticleTask *tasks, int numtasks)
 {
-       ParticleThreadContext *ctx;
        int i;
        
        if (numtasks == 0)
                return;
        
-       ctx = tasks[0].ctx;
+       /* threads */
+       for (i = 0; i < numtasks; ++i) {
+               if (tasks[i].rng)
+                       BLI_rng_free(tasks[i].rng);
+               if (tasks[i].rng_path)
+                       BLI_rng_free(tasks[i].rng_path);
+       }
+
+       MEM_freeN(tasks);
+}
+
+void psys_thread_context_free(ParticleThreadContext *ctx)
+{
        /* path caching */
        if (ctx->vg_length)
                MEM_freeN(ctx->vg_length);
@@ -506,16 +517,6 @@ void psys_tasks_free(ParticleTask *tasks, int numtasks)
        if (ctx->seams) MEM_freeN(ctx->seams);
        //if (ctx->vertpart) MEM_freeN(ctx->vertpart);
        BLI_kdtree_free(ctx->tree);
-
-       /* threads */
-       for (i = 0; i < numtasks; ++i) {
-               if (tasks[i].rng)
-                       BLI_rng_free(tasks[i].rng);
-               if (tasks[i].rng_path)
-                       BLI_rng_free(tasks[i].rng_path);
-       }
-
-       MEM_freeN(tasks);
 }
 
 static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)