From 0f6b29930888c4349d89e08730d2ef3d7d87c673 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 ++++++++++++++++--------- src/lib/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 f14c365..6974428 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); - sd->delay_change_timer = NULL; - efl_event_callback_call(data, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, NULL); + return v; +} - return ECORE_CALLBACK_CANCEL; +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; } 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 1c32c75..5c6d0a9 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; -- 2.7.4