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.
This commit is contained in:
2013-09-23 19:35:21 +00:00
parent eaf354e222
commit fc2dbc20ff
4 changed files with 19 additions and 6 deletions

View File

@@ -564,6 +564,17 @@ static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event
return OPERATOR_PASS_THROUGH; 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 */ /* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{ {
@@ -732,6 +743,7 @@ void RENDER_OT_render(wmOperatorType *ot)
/* api callbacks */ /* api callbacks */
ot->invoke = screen_render_invoke; ot->invoke = screen_render_invoke;
ot->modal = screen_render_modal; ot->modal = screen_render_modal;
ot->cancel = screen_render_cancel;
ot->exec = screen_render_exec; ot->exec = screen_render_exec;
/*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */ /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */

View File

@@ -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 /* stop all running jobs, except screen one. currently previews frustrate Render
* needed to make so sequencer's rendering doesn't conflict with compositor * 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) { if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
/* in case of final rendering used for preview, kill all previews, /* in case of final rendering used for preview, kill all previews,
* otherwise threading conflict will happen in rendering module * 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);
} }
} }

View File

@@ -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(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(struct wmWindowManager *wm);
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); 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); int WM_jobs_has_running(struct wmWindowManager *wm);

View File

@@ -474,13 +474,14 @@ 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; wmJob *wm_job, *next_job;
for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) {
next_job = wm_job->next; next_job = wm_job->next;
if (!owner || wm_job->owner == owner)
if (wm_job->job_type == job_type) if (wm_job->job_type == job_type)
wm_jobs_kill_job(wm, wm_job); wm_jobs_kill_job(wm, wm_job);
} }