Fix #36800: closing render window during render crashes, the operator would be
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 23 Sep 2013 19:35:21 +0000 (19:35 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 23 Sep 2013 19:35:21 +0000 (19:35 +0000)
cancelled before the job, causing invalid access to op->reports in the job thread.

source/blender/editors/render/render_internal.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_jobs.c

index 0f83316edca36717f1eb2d641f8c72f1fa9aeff2..577d8af0caf5b2fe7d4c0ea76a6f9e321c9710c6 100644 (file)
@@ -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 */
index ebec818bb367cb5d628e9149ea8526abf64dbbf2..dca1b4813349d1d8289cdeba30bb8cb7bb0361d1 100644 (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
                 * 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);
                }
        }
 
index f9c18a3e0a224a6a6d4fb26334b3bb89ab045a68..84b376edcd84c71f4d60f58346211a400f896657 100644 (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_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);
 
index 188ad251b8ae96189f3981a39bf5f3c1cada11a5..c9c3d2df7883efaf09686de9d45944d1c6f6d020 100644 (file)
@@ -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);
        }
 }