[Bf-blender-cvs] [45e68e1] blender-v2.77-release: Fix T47971: rigid body baking crash due to thread race condition.

Brecht Van Lommel noreply at git.blender.org
Tue Apr 5 10:39:09 CEST 2016


Commit: 45e68e190dca949d4d2018d587b8f3cbb1000700
Author: Brecht Van Lommel
Date:   Sat Apr 2 04:24:24 2016 +0200
Branches: blender-v2.77-release
https://developer.blender.org/rB45e68e190dca949d4d2018d587b8f3cbb1000700

Fix T47971: rigid body baking crash due to thread race condition.

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

M	source/blender/blenkernel/BKE_pointcache.h
M	source/blender/blenkernel/intern/pointcache.c
M	source/blender/editors/physics/physics_pointcache.c
M	source/blender/render/intern/source/pipeline.c

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

diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 40dbffe..8238ea6 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -190,7 +190,7 @@ typedef struct PTCacheBaker {
 	int render;
 	int anim_init;
 	int quick_step;
-	struct PTCacheID *pid;
+	struct PTCacheID pid;
 
 	void (*update_progress)(void *data, float progress, int *cancel);
 	void *bake_job;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index c8a42d8..448aaaa 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3508,15 +3508,13 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
 {
 	PTCacheBaker baker;
 
-	baker.bake=0;
-	baker.pid=NULL;
-	baker.render=0;
+	memset(&baker, 0, sizeof(baker));
+	baker.main = bmain;
+	baker.scene = scene;
+	baker.bake = 0;
+	baker.render = 0;
 	baker.anim_init = 0;
-	baker.main=bmain;
-	baker.scene=scene;
-	baker.quick_step=scene->physics_settings.quick_cache_step;
-	baker.update_progress = NULL;
-	baker.bake_job = NULL;
+	baker.quick_step = scene->physics_settings.quick_cache_step;
 
 	BKE_ptcache_bake(&baker);
 }
@@ -3541,7 +3539,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
 	Scene *sce_iter; /* SETLOOPER macro only */
 	Base *base;
 	ListBase pidlist;
-	PTCacheID *pid = baker->pid;
+	PTCacheID *pid = &baker->pid;
 	PointCache *cache = NULL;
 	float frameleno = scene->r.framelen;
 	int cfrao = CFRA;
@@ -3552,7 +3550,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
 	G.is_break = false;
 
 	/* set caches to baking mode and figure out start frame */
-	if (pid) {
+	if (pid->ob) {
 		/* cache/bake a single object */
 		cache = pid->cache;
 		if ((cache->flag & PTCACHE_BAKED)==0) {
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index 406b589..e81aa58 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -30,6 +30,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -57,12 +58,7 @@
 
 static int ptcache_bake_all_poll(bContext *C)
 {
-	Scene *scene= CTX_data_scene(C);
-
-	if (!scene)
-		return 0;
-	
-	return 1;
+	return CTX_data_scene(C) != NULL;
 }
 
 static int ptcache_poll(bContext *C)
@@ -77,14 +73,11 @@ typedef struct PointCacheJob {
 	float *progress;
 
 	PTCacheBaker *baker;
-	Object *ob;
-	ListBase pidlist;
 } PointCacheJob;
 
 static void ptcache_job_free(void *customdata)
 {
 	PointCacheJob *job = customdata;
-	BLI_freelistN(&job->pidlist);
 	MEM_freeN(job->baker);
 	MEM_freeN(job);
 }
@@ -149,7 +142,7 @@ static void ptcache_job_endjob(void *customdata)
 	WM_set_locked_interface(G.main->wm.first, false);
 
 	WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
-	WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->ob);
+	WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
 }
 
 static void ptcache_free_bake(PointCache *cache)
@@ -166,32 +159,60 @@ static void ptcache_free_bake(PointCache *cache)
 	}
 }
 
-static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
+static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
 {
-	Main *bmain = CTX_data_main(C);
-	Scene *scene = CTX_data_scene(C);
+	PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
 
-	PTCacheBaker *baker = MEM_mallocN(sizeof(PTCacheBaker), "PTCacheBaker");
-
-	baker->main = bmain;
-	baker->scene = scene;
-	baker->pid = NULL;
+	baker->main = CTX_data_main(C);
+	baker->scene = CTX_data_scene(C);
 	baker->bake = RNA_boolean_get(op->ptr, "bake");
 	baker->render = 0;
 	baker->anim_init = 0;
 	baker->quick_step = 1;
-	baker->update_progress = ptcache_job_update;
 
-	PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
-	job->baker = baker;
-	job->ob = NULL;
-	job->pidlist.first = NULL;
-	job->pidlist.last = NULL;
+	if (!all) {
+		PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+		Object *ob = ptr.id.data;
+		PointCache *cache = ptr.data;
+
+		ListBase pidlist;
+		BKE_ptcache_ids_from_object(&pidlist, ob, baker->scene, MAX_DUPLI_RECUR);
+
+		for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
+			if (pid->cache == cache) {
+				baker->pid = *pid;
+				break;
+			}
+		}
 
-	baker->bake_job = job;
+		BLI_freelistN(&pidlist);
+	}
 
-	wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Point Cache",
-	                            WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE);
+	return baker;
+}
+
+static int ptcache_bake_exec(bContext *C, wmOperator *op)
+{
+	bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
+
+	PTCacheBaker *baker = ptcache_baker_create(C, op, all);
+	BKE_ptcache_bake(baker);
+	MEM_freeN(baker);
+
+	return OPERATOR_FINISHED;
+}
+
+static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+	bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
+
+	PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
+	job->baker = ptcache_baker_create(C, op, all);
+	job->baker->bake_job = job;
+	job->baker->update_progress = ptcache_job_update;
+
+	wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_data_scene(C),
+	                            "Point Cache", WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE);
 
 	WM_jobs_customdata_set(wm_job, job, ptcache_job_free);
 	WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE);
@@ -201,7 +222,33 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
 
 	WM_jobs_start(CTX_wm_manager(C), wm_job);
 
-	return OPERATOR_FINISHED;
+	WM_event_add_modal_handler(C, op);
+
+	/* we must run modal until the bake job is done, otherwise the undo push
+	 * happens before the job ends, which can lead to race conditions between
+	 * the baking and file writing code */
+	return OPERATOR_RUNNING_MODAL;
+}
+
+static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+	Scene *scene = (Scene *) op->customdata;
+
+	/* no running blender, remove handler and pass through */
+	if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_POINTCACHE)) {
+		return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+	}
+
+	return OPERATOR_PASS_THROUGH;
+}
+
+static void ptcache_bake_cancel(bContext *C, wmOperator *op)
+{
+	wmWindowManager *wm = CTX_wm_manager(C);
+	Scene *scene = (Scene *) op->customdata;
+
+	/* kill on cancel, because job is using op->reports */
+	WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_POINTCACHE);
 }
 
 static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
@@ -236,7 +283,10 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
 	ot->idname = "PTCACHE_OT_bake_all";
 	
 	/* api callbacks */
-	ot->exec = ptcache_bake_all_exec;
+	ot->exec = ptcache_bake_exec;
+	ot->invoke = ptcache_bake_invoke;
+	ot->modal = ptcache_bake_modal;
+	ot->cancel = ptcache_bake_cancel;
 	ot->poll = ptcache_bake_all_poll;
 
 	/* flags */
@@ -259,53 +309,6 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static int ptcache_bake_exec(bContext *C, wmOperator *op)
-{
-	Main *bmain = CTX_data_main(C);
-	Scene *scene = CTX_data_scene(C);
-	PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
-	Object *ob = ptr.id.data;
-	PointCache *cache = ptr.data;
-
-	PTCacheBaker *baker = MEM_mallocN(sizeof(PTCacheBaker), "PTCacheBaker");
-	baker->main = bmain;
-	baker->scene = scene;
-	baker->bake = RNA_boolean_get(op->ptr, "bake");
-	baker->render = 0;
-	baker->anim_init = 0;
-	baker->quick_step = 1;
-	baker->update_progress = ptcache_job_update;
-	baker->pid = NULL;
-
-	PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
-	job->baker = baker;
-	job->ob = ob;
-
-	BKE_ptcache_ids_from_object(&job->pidlist, ob, scene, MAX_DUPLI_RECUR);
-
-	for (PTCacheID *pid = job->pidlist.first; pid; pid = pid->next) {
-		if (pid->cache == cache) {
-			baker->pid = pid;
-			break;
-		}
-	}
-
-	baker->bake_job = job;
-
-	wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Point Cache",
-	                            WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE);
-
-	WM_jobs_customdata_set(wm_job, job, ptcache_job_free);
-	WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE);
-	WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob);
-
-	WM_set_locked_interface(CTX_wm_manager(C), true);
-
-	WM_jobs_start(CTX_wm_manager(C), wm_job);
-
-	return OPERATOR_FINISHED;
-}
-
 static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
@@ -339,6 +342,9 @@ void PTCACHE_OT_bake(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec = ptcache_bake_exec;
+	ot->invoke = ptcache_bake_invoke;
+	ot->modal = ptcache_bake_modal;
+	ot->cancel = ptcache_bake_cancel;
 	ot->poll = ptcache_poll;
 
 	/* flags */
@@ -441,7 +447,7 @@ void PTCACHE_OT_add(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec = ptcache_add_new_exec;
-	ot->poll = ptcache_poll; // ptcache_bake_all_poll;
+	ot->poll = ptcache_poll;
 
 	/* flags */
 	ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 6fef581..f7e35a4 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -3061,15 +3061,13 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)
 {
 	PTCacheBaker baker;
 
+	memset(&baker, 0, sizeof(baker));
 	baker.main = re->main;
 	baker.scene = scene;
-	baker.pid = NULL;
 	baker.bake = 0;
 	baker.render = 1;
 	baker.anim_init = 1;
 	baker.quick_step = 1;
-	baker.update_progress = NULL;
-	baker.bake_job = NULL;
 
 	BKE_ptcache_bake(&baker);
 }




More information about the Bf-blender-cvs mailing list