From 58c477a30a513b15f2c10e2e61bdb80018ef8fdb Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 3 Jun 2016 16:57:53 -0700 Subject: [PATCH] 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 7520ce53ef..5a011a43c6 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) {