From 477611f01460f4b9881f2b5dd4b88f463d8f81b0 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 11 Jul 2019 15:53:54 -0700 Subject: [PATCH] elementary: fix potential race condition by using Eina_Future attached to the object. I get some random segfault in elementary test suite pointing to this code. Most likely we do not properly destroy the timer during destruction. Could be because we initiate a delay while destruction is going on or something like that. Anyway, it is easier and more robust to get it fixed by linking the lifetime of the timeout to the lifetime of the widget as future allow us to do easily. Reviewed-by: Marcel Hollerbach Differential Revision: https://phab.enlightenment.org/D9298 --- src/lib/elementary/efl_ui_spin_button.c | 27 ++++++++++++------- .../elementary/efl_ui_spin_button_private.h | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/lib/elementary/efl_ui_spin_button.c b/src/lib/elementary/efl_ui_spin_button.c index f14c365ba8..6974428dc4 100644 --- a/src/lib/elementary/efl_ui_spin_button.c +++ b/src/lib/elementary/efl_ui_spin_button.c @@ -113,15 +113,20 @@ _label_write(Evas_Object *obj) eina_strbuf_free(strbuf); } -static Eina_Bool -_delay_change_timer_cb(void *data) +static Eina_Value +_delay_change_timer_cb(Eo *o, void *data EINA_UNUSED, const Eina_Value v) { - Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS); + efl_event_callback_call(o, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, NULL); + + return v; +} + +static void +_delay_change_timer_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED) +{ + Efl_Ui_Spin_Button_Data *sd = data; sd->delay_change_timer = NULL; - efl_event_callback_call(data, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, NULL); - - return ECORE_CALLBACK_CANCEL; } static Eina_Bool @@ -130,6 +135,7 @@ _value_set(Evas_Object *obj, { Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS); Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS); + Eina_Future *f; if (sd->circulate) { @@ -146,9 +152,12 @@ _value_set(Evas_Object *obj, if (EINA_DBL_EQ(new_val, efl_ui_range_value_get(obj))) return EINA_TRUE; efl_ui_range_value_set(obj, new_val); - ecore_timer_del(sd->delay_change_timer); - sd->delay_change_timer = ecore_timer_add(EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME, - _delay_change_timer_cb, obj); + if (sd->delay_change_timer) eina_future_cancel(sd->delay_change_timer); + f = efl_loop_timeout(efl_loop_get(obj), EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME); + sd->delay_change_timer = efl_future_then(obj, f, + .success = _delay_change_timer_cb, + .free = _delay_change_timer_cleanup, + .data = sd); return EINA_TRUE; } diff --git a/src/lib/elementary/efl_ui_spin_button_private.h b/src/lib/elementary/efl_ui_spin_button_private.h index 1c32c75a6d..5c6d0a977b 100644 --- a/src/lib/elementary/efl_ui_spin_button_private.h +++ b/src/lib/elementary/efl_ui_spin_button_private.h @@ -5,7 +5,7 @@ typedef struct _Efl_Ui_Spin_Button_Data Efl_Ui_Spin_Button_Data; struct _Efl_Ui_Spin_Button_Data { Evas_Object *ent, *inc_button, *dec_button, *text_button; - Ecore_Timer *delay_change_timer; /**< a timer for a delay,changed smart callback */ + Eina_Future *delay_change_timer; /**< a timer for a delay,changed smart callback */ Efl_Ui_Layout_Orientation dir;