fix for crash with demo mode addon, modal operator loading a blend file would free all window data which was then accessed, causing a crash.

This commit is contained in:
Campbell Barton 2011-09-28 15:42:55 +00:00
parent 35f881b44d
commit b88776ba5a
2 changed files with 48 additions and 34 deletions

@ -6238,7 +6238,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
ParameterIterator iter;
PointerRNA funcptr;
int err= 0, i, flag, ret_len=0;
int is_static= RNA_function_flag(func) & FUNC_NO_SELF;
const char is_static= (RNA_function_flag(func) & FUNC_NO_SELF) != 0;
/* annoying!, need to check if the screen gets set to NULL which is a
* hint that the file was actually re-loaded. */
const char is_valid_screen= (CTX_wm_screen(C) != NULL);
PropertyRNA *pret_single= NULL;
void *retdata_single= NULL;
@ -6498,7 +6502,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if(err != 0) {
ReportList *reports;
/* alert the user, else they wont know unless they see the console. */
if (!is_static && ptr->data && RNA_struct_is_a(ptr->type, &RNA_Operator)) {
if ( (!is_static) &&
(ptr->data) &&
(RNA_struct_is_a(ptr->type, &RNA_Operator)) &&
is_valid_screen == (CTX_wm_screen(C) != NULL))
{
wmOperator *op= ptr->data;
reports= op->reports;
}

@ -1223,41 +1223,47 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
retval= ot->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
if(ot->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm)
wm->op_undo_depth--;
/* when this is _not_ the case the modal modifier may have loaded
* a new blend file (demo mode does this), so we have to assume
* the event, operator etc have all been freed. - campbell */
if(CTX_wm_manager(C) == wm) {
/* putting back screen context, reval can pass trough after modal failures! */
if((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
}
else {
/* this special cases is for areas and regions that get removed */
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
if(ot->flag & OPTYPE_UNDO)
wm->op_undo_depth--;
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED))
wm_operator_reports(C, op, retval, 0);
if(retval & OPERATOR_FINISHED) {
wm_operator_finished(C, op, 0);
handler->op= NULL;
}
else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
WM_operator_free(op);
handler->op= NULL;
}
/* remove modal handler, operator itself should have been cancelled and freed */
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
WM_cursor_ungrab(CTX_wm_window(C));
/* putting back screen context, reval can pass trough after modal failures! */
if((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
}
else {
/* this special cases is for areas and regions that get removed */
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
}
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
/* prevent silly errors from operator users */
//retval &= ~OPERATOR_PASS_THROUGH;
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED))
wm_operator_reports(C, op, retval, 0);
if(retval & OPERATOR_FINISHED) {
wm_operator_finished(C, op, 0);
handler->op= NULL;
}
else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
WM_operator_free(op);
handler->op= NULL;
}
/* remove modal handler, operator itself should have been cancelled and freed */
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
WM_cursor_ungrab(CTX_wm_window(C));
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);
/* prevent silly errors from operator users */
//retval &= ~OPERATOR_PASS_THROUGH;
}
}
}