floatingbutton: fix crash issues caused by unhandled timer callbacks
authorYoungbok Shin <youngb.shin@samsung.com>
Thu, 3 May 2018 09:52:28 +0000 (18:52 +0900)
committerJongmin Lee <jm105.lee@samsung.com>
Thu, 21 Jun 2018 22:26:36 +0000 (07:26 +0900)
An Ecore_Timer has to removed when a related object is deleted.
So, floatingbutton must have its own destructor function to remove its timer.
In addition, during processing its super's destructor function,
_update_pos function can be called. It will add another unhandled timer callback.
So, we need to remove all event/signal callbacks to blocking meaningless works.

It also remove warning messages and minor issues.

Change-Id: Ieedc7564c3b521d501d83abbd3453d491c504334

src/mobile/eext_floatingbutton.c
src/mobile/eext_floatingbutton.eo

index 2c6a0186e3db0a31843902b8b5f79ed433dbb020..0cbfc481620a864871de72ca2259f14dacb1ef9c 100644 (file)
@@ -73,6 +73,7 @@ typedef struct _Eext_Floatingbutton_Data {
    Evas_Object             *vg;
    Efl_VG     *base_shape;
    Ecore_Animator          *anim;
+   Ecore_Timer             *threshold_update_timer;
 
    Evas_Object             *btn1;
    Evas_Object             *btn2;
@@ -101,6 +102,8 @@ struct _Eext_Floatingbutton_Part_Data
    Eina_Tmpstr    *part;
 };
 
+static void _btn_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
+
 static void
 _signal_emit(Eo *obj, Eext_Floatingbutton_Data *sd)
 {
@@ -129,7 +132,7 @@ _signal_emit(Eo *obj, Eext_Floatingbutton_Data *sd)
          edje_object_signal_emit(edje, buf, "elm");
          sd->center = EINA_FALSE;
          break;
-      case EEXT_FLOATINGBUTTON_LAST:
+      default:
          /* you must not reach here */
          break;
      }
@@ -223,13 +226,14 @@ _anim_cb(void *data, double pos)
 }
 
 static Eina_Bool
-_message_send(void *data)
+_threshold_update_timer_cb(void *data)
 {
    Eext_Floatingbutton_Data *fbd = data;
 
+   fbd->threshold_update_timer = NULL;
    _threshold_update(fbd->obj, fbd);
 
-   return ECORE_CALLBACK_CANCEL;
+   return ECORE_CALLBACK_DONE;
 }
 
 static void
@@ -260,7 +264,10 @@ _update_pos(Eo *obj, Eext_Floatingbutton_Data *fbd, Eina_Bool anim)
    fbd->on_update = EINA_FALSE;
 
    if (!anim || fbd->anim)
-     ecore_timer_add(0.4, _message_send, fbd);
+     {
+        if (fbd->threshold_update_timer) ecore_timer_del(fbd->threshold_update_timer);
+        fbd->threshold_update_timer = ecore_timer_add(0.4, _threshold_update_timer_cb, fbd);
+     }
 }
 
 static void
@@ -271,7 +278,7 @@ _resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info E
 }
 
 static void
-_size_hints_changed_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+_size_hints_changed_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
 {
    Evas_Display_Mode dispmode;
 
@@ -508,7 +515,7 @@ _eext_floatingbutton_efl_object_constructor(Eo *obj, Eext_Floatingbutton_Data *s
      CRI("Failed to set layout!");
 
    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, sd);
-   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, sd);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, NULL);
 
    elm_layout_signal_callback_add(obj, "mouse,down,1", DRAGABLE_PART, _on_mouse_down, sd);
    elm_layout_signal_callback_add(obj, "mouse,up,1", DRAGABLE_PART, _on_mouse_up, sd);
@@ -547,6 +554,37 @@ _eext_floatingbutton_efl_object_constructor(Eo *obj, Eext_Floatingbutton_Data *s
    return obj;
 }
 
+EOLIAN static void
+_eext_floatingbutton_efl_object_destructor(Eo *obj, Eext_Floatingbutton_Data *sd)
+{
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize_cb, sd);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb, NULL);
+   elm_layout_signal_callback_del(obj, "mouse,down,1", DRAGABLE_PART, _on_mouse_down);
+   elm_layout_signal_callback_del(obj, "mouse,up,1", DRAGABLE_PART, _on_mouse_up);
+   elm_layout_signal_callback_del(obj, "mouse,move", DRAGABLE_PART, _on_mouse_move);
+   evas_object_event_callback_del_full(sd->vg, EVAS_CALLBACK_RESIZE, _vg_resize_cb, sd);
+
+   if (sd->btn1)
+     {
+        evas_object_event_callback_del_full(sd->btn1, EVAS_CALLBACK_DEL, _btn_del_cb, obj);
+        sd->btn1 = NULL;
+     }
+
+   if (sd->btn2)
+     {
+        evas_object_event_callback_del_full(sd->btn2, EVAS_CALLBACK_DEL, _btn_del_cb, obj);
+        sd->btn2 = NULL;
+     }
+
+   if (sd->threshold_update_timer)
+     {
+        ecore_timer_del(sd->threshold_update_timer);
+        sd->threshold_update_timer = NULL;
+     }
+
+   efl_destructor(efl_super(obj, MY_CLASS));
+}
+
 EOLIAN static void
 _eext_floatingbutton_class_constructor(Efl_Class *klass)
 {
@@ -566,7 +604,7 @@ _btn_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info
    if (fbd->btn1 == obj) fbd->btn1 = NULL;
    else if (fbd->btn2 == obj) fbd->btn2 = NULL;
 
-   _update_pos(obj, fbd, EINA_FALSE);
+   _update_pos(data, fbd, EINA_FALSE);
 }
 
 EOLIAN static Efl_Ui_Theme_Apply
@@ -618,6 +656,9 @@ _eext_floatingbutton_floatingbutton_mode_set(Eo *obj,
         sd->pos_disabled[EEXT_FLOATINGBUTTON_RIGHT] = 0;
         sd->pos_disabled[EEXT_FLOATINGBUTTON_RIGHT_OUT] = 1;
         break;
+      default:
+        /* you must not reach here */
+        break;
      }
 }
 
index d26a996c66b1048b5910c0d9dded47a4c89773f1..ae5c717e4ed34bd8897bb632fc1ac8dad1704a15 100644 (file)
@@ -108,6 +108,7 @@ class Eext.Floatingbutton (Efl.Ui.Layout.Object, Efl.Access.Component) {
    implements {
       class.constructor;
       Efl.Object.constructor;
+      Efl.Object.destructor;
       Efl.Ui.Base.mirrored { get; set; }
       Efl.Ui.Widget.theme_apply;
       Efl.Access.Component.extents { get; }