summaryrefslogtreecommitdiff
path: root/src/lib/elementary/efl_ui_spin_button.c
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-07-11 15:53:54 -0700
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-07-17 21:57:59 +0200
commit477611f01460f4b9881f2b5dd4b88f463d8f81b0 (patch)
tree839cd0eeb4a3f486f8dc41ae71ab49da00f6f5a0 /src/lib/elementary/efl_ui_spin_button.c
parent83700fe13c495193d72c95e906c0866e39c6e5c9 (diff)
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 <mail@marcel-hollerbach.de> Differential Revision: https://phab.enlightenment.org/D9298
Diffstat (limited to 'src/lib/elementary/efl_ui_spin_button.c')
-rw-r--r--src/lib/elementary/efl_ui_spin_button.c27
1 files changed, 18 insertions, 9 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)
113 eina_strbuf_free(strbuf); 113 eina_strbuf_free(strbuf);
114} 114}
115 115
116static Eina_Bool 116static Eina_Value
117_delay_change_timer_cb(void *data) 117_delay_change_timer_cb(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
118{ 118{
119 Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS); 119 efl_event_callback_call(o, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, NULL);
120 120
121 sd->delay_change_timer = NULL; 121 return v;
122 efl_event_callback_call(data, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, NULL); 122}
123 123
124 return ECORE_CALLBACK_CANCEL; 124static void
125_delay_change_timer_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
126{
127 Efl_Ui_Spin_Button_Data *sd = data;
128
129 sd->delay_change_timer = NULL;
125} 130}
126 131
127static Eina_Bool 132static Eina_Bool
@@ -130,6 +135,7 @@ _value_set(Evas_Object *obj,
130{ 135{
131 Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS); 136 Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
132 Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS); 137 Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS);
138 Eina_Future *f;
133 139
134 if (sd->circulate) 140 if (sd->circulate)
135 { 141 {
@@ -146,9 +152,12 @@ _value_set(Evas_Object *obj,
146 if (EINA_DBL_EQ(new_val, efl_ui_range_value_get(obj))) return EINA_TRUE; 152 if (EINA_DBL_EQ(new_val, efl_ui_range_value_get(obj))) return EINA_TRUE;
147 153
148 efl_ui_range_value_set(obj, new_val); 154 efl_ui_range_value_set(obj, new_val);
149 ecore_timer_del(sd->delay_change_timer); 155 if (sd->delay_change_timer) eina_future_cancel(sd->delay_change_timer);
150 sd->delay_change_timer = ecore_timer_add(EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME, 156 f = efl_loop_timeout(efl_loop_get(obj), EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME);
151 _delay_change_timer_cb, obj); 157 sd->delay_change_timer = efl_future_then(obj, f,
158 .success = _delay_change_timer_cb,
159 .free = _delay_change_timer_cleanup,
160 .data = sd);
152 161
153 return EINA_TRUE; 162 return EINA_TRUE;
154} 163}