raster pushed a commit to branch efl-1.20. http://git.enlightenment.org/core/efl.git/commit/?id=fcea581d6106bc223049123d54281a7d04275668
commit fcea581d6106bc223049123d54281a7d04275668 Author: Carsten Haitzler (Rasterman) <[email protected]> Date: Sat Aug 5 13:10:33 2017 +0900 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 --- src/lib/edje/edje_callbacks.c | 26 +++++++++++++++++++++----- src/lib/edje/edje_private.h | 1 + src/lib/edje/edje_program.c | 41 ++++++++++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/lib/edje/edje_callbacks.c b/src/lib/edje/edje_callbacks.c index ac6f52c9eb..06ed0f81a7 100644 --- a/src/lib/edje/edje_callbacks.c +++ b/src/lib/edje/edje_callbacks.c @@ -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); diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index af7075208f..b29d77f4a9 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -2058,6 +2058,7 @@ struct _Edje_Running_Program Edje *edje; Edje_Program *program; double start_time; + unsigned short ref; Eina_Bool delete_me : 1; }; diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c index 28b9300ccf..c5c915e220 100644 --- a/src/lib/edje/edje_program.c +++ b/src/lib/edje/edje_program.c @@ -387,20 +387,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; } } @@ -522,7 +534,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) @@ -535,14 +554,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; } @@ -601,7 +628,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 --
