diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-09-23 23:35:21 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-09-23 23:35:21 +0400 |
commit | fc2dbc20ff5c9187310e8d51dca99c7be13b84b4 (patch) | |
tree | 691f688fe7047196d382af92f257eb71df7affef | |
parent | eaf354e222ec64dc0e258a53107ef1eca9ac341c (diff) |
Fix #36800: closing render window during render crashes, the operator would be
cancelled before the job, causing invalid access to op->reports in the job thread.
-rw-r--r-- | source/blender/editors/render/render_internal.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_sequencer/sequencer_draw.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_jobs.c | 7 |
4 files changed, 19 insertions, 6 deletions
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 0f83316edca..577d8af0caf 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -564,6 +564,17 @@ static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event return OPERATOR_PASS_THROUGH; } +static int screen_render_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_RENDER); + + return OPERATOR_CANCELLED; +} + /* using context, starts job */ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -732,6 +743,7 @@ void RENDER_OT_render(wmOperatorType *ot) /* api callbacks */ ot->invoke = screen_render_invoke; ot->modal = screen_render_modal; + ot->cancel = screen_render_cancel; ot->exec = screen_render_exec; /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index ebec818bb36..dca1b481334 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -926,13 +926,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* stop all running jobs, except screen one. currently previews frustrate Render * needed to make so sequencer's rendering doesn't conflict with compositor */ - WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE); + WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE); if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* in case of final rendering used for preview, kill all previews, * otherwise threading conflict will happen in rendering module */ - WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW); + WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW); } } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index f9c18a3e0a2..84b376edcd8 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -393,7 +393,7 @@ void WM_jobs_stop(struct wmWindowManager *wm, void *owner, void *startjob); void WM_jobs_kill(struct wmWindowManager *wm, void *owner, void (*)(void *, short int *, short int *, float *)); void WM_jobs_kill_all(struct wmWindowManager *wm); void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); -void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type); +void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type); int WM_jobs_has_running(struct wmWindowManager *wm); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 188ad251b8a..c9c3d2df788 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -474,15 +474,16 @@ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) } -void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type) +void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type) { wmJob *wm_job, *next_job; for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { next_job = wm_job->next; - if (wm_job->job_type == job_type) - wm_jobs_kill_job(wm, wm_job); + if (!owner || wm_job->owner == owner) + if (wm_job->job_type == job_type) + wm_jobs_kill_job(wm, wm_job); } } |