cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=58c477a30a513b15f2c10e2e61bdb80018ef8fdb
commit 58c477a30a513b15f2c10e2e61bdb80018ef8fdb Author: Cedric BAIL <ced...@osg.samsung.com> Date: Fri Jun 3 16:57:53 2016 -0700 ecore: properly handle double free case of timeout promise. The bug came from the fact we need to handle the destruction of the main loop which destroy the underlying timer. The event handler that catch the destruction of the timer can not make the difference between eo_del call from the timeout code and eo_del from the main loop destruction. By removing the event handler, the double free is properly avoided. --- src/lib/ecore/ecore_main.c | 65 +++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 7520ce5..5a011a4 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -2826,18 +2826,6 @@ _efl_loop_job_cb(void *data) free(j); } -static Eina_Bool -_efl_loop_timeout_cb(void *data, const Eo_Event *event EINA_UNUSED) -{ - Efl_Internal_Promise *t = data; - - eina_promise_owner_value_set(t->promise, t->data, NULL); - - eo_del(t->u.timer); - - return EO_CALLBACK_CONTINUE; -} - static void _efl_loop_args_job_cb(void *data, void *value EINA_UNUSED) { @@ -2860,6 +2848,37 @@ _efl_loop_args_add(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, int argc, const char eina_promise_then(job, _efl_loop_args_job_cb, NULL, args); } +static Eina_Bool _efl_loop_timeout_force_cancel_cb(void *data, const Eo_Event *event EINA_UNUSED); +static Eina_Bool _efl_loop_timeout_cb(void *data, const Eo_Event *event EINA_UNUSED); + +EO_CALLBACKS_ARRAY_DEFINE(timeout, + { EFL_LOOP_TIMER_EVENT_TICK, _efl_loop_timeout_cb }, + { EO_EVENT_DEL, _efl_loop_timeout_force_cancel_cb }); + +/* This event will be triggered when the main loop is destroyed and destroy its timers along */ +static void _efl_loop_internal_cancel(Efl_Internal_Promise *p); + +static Eina_Bool +_efl_loop_timeout_force_cancel_cb(void *data, const Eo_Event *event EINA_UNUSED) +{ + _efl_loop_internal_cancel(data); + + return EO_CALLBACK_CONTINUE; +} + +static Eina_Bool +_efl_loop_timeout_cb(void *data, const Eo_Event *event EINA_UNUSED) +{ + Efl_Internal_Promise *t = data; + + eina_promise_owner_value_set(t->promise, t->data, NULL); + + eo_event_callback_array_del(t->u.timer, timeout(), t); + eo_del(t->u.timer); + + return EO_CALLBACK_CONTINUE; +} + static void _efl_loop_internal_cancel(Efl_Internal_Promise *p) { @@ -2875,9 +2894,14 @@ _efl_loop_job_cancel(void* data, Eina_Promise_Owner* promise EINA_UNUSED) if (j->job_is) { ecore_job_del(j->u.job); - _efl_loop_internal_cancel(j); } - else eo_del(j->u.timer); + else + { + eo_event_callback_array_del(j->u.timer, timeout(), j); + eo_del(j->u.timer); + } + + _efl_loop_internal_cancel(j); } static Efl_Internal_Promise * @@ -2920,19 +2944,6 @@ _efl_loop_job(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED, const void *da return NULL; } -/* This event will be triggered when the main loop is destroyed and destroy its timers along */ -static Eina_Bool -_efl_loop_timeout_force_cancel_cb(void *data, const Eo_Event *event EINA_UNUSED) -{ - _efl_loop_internal_cancel(data); - - return EO_CALLBACK_CONTINUE; -} - -EO_CALLBACKS_ARRAY_DEFINE(timeout, - { EFL_LOOP_TIMER_EVENT_TICK, _efl_loop_timeout_cb }, - { EO_EVENT_DEL, _efl_loop_timeout_force_cancel_cb }); - static Eina_Promise * _efl_loop_timeout(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, double time, const void *data) { --