edje crash with run program references - fix

i found a crash today where a heme could cause a crash if it just did
the right things. the run program was freed while still being
accessed. so add some ref counting to keep it alive until references
go to 0. and add soem refs while we store it in lists.

@fix
This commit is contained in:
Carsten Haitzler 2017-08-05 13:10:33 +09:00
parent fb153fc57a
commit 7b59a4851e
3 changed files with 56 additions and 12 deletions

View File

@ -387,35 +387,51 @@ _edje_timer_cb(void *data, const Efl_Event *event EINA_UNUSED)
_edje_util_freeze(ed);
if ((!ed->paused) && (!ed->delete_me))
{
const void *tmp;
Edje_Running_Program *tmp;
ed->walking_actions = EINA_TRUE;
EINA_LIST_FOREACH(ed->actions, l, tmp)
newl = eina_list_append(newl, tmp);
{
tmp->ref++;
newl = eina_list_append(newl, tmp);
}
while (newl)
{
Edje_Running_Program *runp;
runp = eina_list_data_get(newl);
newl = eina_list_remove(newl, eina_list_data_get(newl));
runp->ref--;
if (!runp->delete_me)
_edje_program_run_iterate(runp, t);
if (_edje_block_break(ed))
{
eina_list_free(newl);
EINA_LIST_FREE(newl, tmp)
{
tmp->ref--;
if ((tmp->delete_me) && (tmp->ref == 0))
{
_edje_program_run_cleanup(ed, tmp);
free(tmp);
}
}
newl = NULL;
goto break_prog;
}
}
EINA_LIST_FOREACH(ed->actions, l, tmp)
newl = eina_list_append(newl, tmp);
{
tmp->ref++;
newl = eina_list_append(newl, tmp);
}
while (newl)
{
Edje_Running_Program *runp;
runp = eina_list_data_get(newl);
newl = eina_list_remove(newl, eina_list_data_get(newl));
if (runp->delete_me)
runp->ref--;
if ((runp->delete_me) && (runp->ref == 0))
{
_edje_program_run_cleanup(ed, runp);
free(runp);

View File

@ -2059,6 +2059,7 @@ struct _Edje_Running_Program
Edje *edje;
Edje_Program *program;
double start_time;
unsigned short ref;
Eina_Bool delete_me : 1;
};

View File

@ -299,20 +299,32 @@ _edje_object_animation_set(Eo *obj, Edje *ed, Eina_Bool on)
if (!on)
{
Eina_List *newl = NULL;
const void *data;
Edje_Running_Program *data;
EINA_LIST_FOREACH(ed->actions, l, data)
newl = eina_list_append(newl, data);
{
data->ref++;
newl = eina_list_append(newl, data);
}
while (newl)
{
Edje_Running_Program *runp;
runp = eina_list_data_get(newl);
newl = eina_list_remove(newl, eina_list_data_get(newl));
runp->ref--;
_edje_program_run_iterate(runp, runp->start_time + TO_DOUBLE(runp->program->tween.time));
if (_edje_block_break(ed))
{
eina_list_free(newl);
EINA_LIST_FREE(newl, data)
{
data->ref--;
if ((data->delete_me) && (data->ref == 0))
{
_edje_program_run_cleanup(ed, data);
free(data);
}
}
goto break_prog;
}
}
@ -434,7 +446,14 @@ _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
// _edje_emit(ed, "program,stop", runp->program->name);
if (_edje_block_break(ed))
{
if (!ed->walking_actions) free(runp);
if (!ed->walking_actions)
{
if (runp->ref == 0)
{
_edje_program_run_cleanup(ed, runp);
free(runp);
}
}
goto break_prog;
}
EINA_LIST_FOREACH(runp->program->after, l, pa)
@ -447,14 +466,22 @@ _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
if (pr) _edje_program_run(ed, pr, 0, "", "");
if (_edje_block_break(ed))
{
if (!ed->walking_actions) free(runp);
if ((!ed->walking_actions) && (runp->ref == 0))
{
_edje_program_run_cleanup(ed, runp);
free(runp);
}
goto break_prog;
}
}
}
_edje_util_thaw(ed);
_edje_unref(ed);
if (!ed->walking_actions) free(runp);
if ((!ed->walking_actions) && (runp->ref == 0))
{
_edje_program_run_cleanup(ed, runp);
free(runp);
}
_edje_unblock(ed);
return EINA_FALSE;
}
@ -513,7 +540,7 @@ _edje_program_end(Edje *ed, Edje_Running_Program *runp)
// _edje_emit(ed, "program,stop", pname);
_edje_util_thaw(ed);
_edje_unref(ed);
if (free_runp) free(runp);
if ((free_runp) && (runp->ref == 0)) free(runp);
}
#ifdef HAVE_EPHYSICS