elm_widget: fix widget signal callback memory leak.
authorCedric Bail <cedric.bail@samsung.com>
Wed, 25 Sep 2013 07:41:12 +0000 (16:41 +0900)
committerCedric Bail <cedric.bail@samsung.com>
Wed, 25 Sep 2013 07:41:12 +0000 (16:41 +0900)
Thanks to bluezery D228 for pointing out the issue.

src/lib/elm_widget.c

index ca3d375..77b8700 100644 (file)
@@ -4956,6 +4956,40 @@ _track_obj_del(void *data, Evas *e EINA_UNUSED,
                                   _track_obj_view_del);
 }
 
+static void
+_elm_widget_item_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission,
+                           const char *source)
+{
+   Elm_Widget_Item_Signal_Data *wisd = data;
+   wisd->func(wisd->data, wisd->item, emission, source);
+}
+
+static void *
+_elm_widget_item_signal_callback_list_get(Elm_Widget_Item *item, Eina_List *position)
+{
+   Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
+   void *data;
+
+   item->signals = eina_list_remove_list(item->signals, position);
+   data = wisd->data;
+
+   if (_elm_widget_is(item->view))
+     elm_object_signal_callback_del(item->view,
+                                    wisd->emission, wisd->source,
+                                    _elm_widget_item_signal_cb);
+   else if (!strcmp(eo_class_name_get(eo_class_get(item->view)),
+                    "edje"))
+     edje_object_signal_callback_del_full(item->view,
+                                          wisd->emission, wisd->source,
+                                          _elm_widget_item_signal_cb, wisd);
+
+   eina_stringshare_del(wisd->emission);
+   eina_stringshare_del(wisd->source);
+   free(wisd);
+
+   return data;
+}
+
 
 /**
  * @internal
@@ -5000,7 +5034,6 @@ EAPI void
 _elm_widget_item_free(Elm_Widget_Item *item)
 {
    Elm_Translate_String_Data *ts;
-   Elm_Widget_Item_Signal_Data *wisd;
 
    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
 
@@ -5013,12 +5046,8 @@ _elm_widget_item_free(Elm_Widget_Item *item)
    if (item->access_info)
      eina_stringshare_del(item->access_info);
 
-   EINA_LIST_FREE(item->signals, wisd)
-     {
-        eina_stringshare_del(wisd->emission);
-        eina_stringshare_del(wisd->source);
-        free(wisd);
-     }
+   while (item->signals)
+     _elm_widget_item_signal_callback_list_get(item, item->signals);
 
    while (item->translate_strings)
      {
@@ -5913,14 +5942,6 @@ _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
    item->signal_emit_func = func;
 }
 
-static void
-_elm_widget_item_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission,
-                           const char *source)
-{
-   Elm_Widget_Item_Signal_Data *wisd = data;
-   wisd->func(wisd->data, wisd->item, emission, source);
-}
-
 EAPI void
 _elm_widget_item_signal_callback_add(Elm_Widget_Item *item,
                                      const char *emission,
@@ -5963,36 +5984,21 @@ _elm_widget_item_signal_callback_del(Elm_Widget_Item *item,
                                     const char *source,
                                     Elm_Widget_Item_Signal_Cb func)
 {
-   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
-
    Elm_Widget_Item_Signal_Data *wisd;
    Eina_List *l;
-   void *data = NULL;
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
 
    EINA_LIST_FOREACH(item->signals, l, wisd)
      {
-        if ((wisd->func == func) && !strcmp(wisd->emission, emission) &&
+        if ((wisd->func == func) &&
+            !strcmp(wisd->emission, emission) &&
             !strcmp(wisd->source, source))
-          {
-             item->signals = eina_list_remove_list(item->signals, l);
-             eina_stringshare_del(wisd->emission);
-             eina_stringshare_del(wisd->source);
-             data = wisd->data;
-
-             if (_elm_widget_is(item->view))
-               elm_object_signal_callback_del(item->view, emission, source,
-                                              _elm_widget_item_signal_cb);
-             else if (!strcmp(eo_class_name_get(eo_class_get(item->view)),
-                              "edje"))
-               edje_object_signal_callback_del_full(item->view, emission,
-                                                    source,
-                                                    _elm_widget_item_signal_cb,
-                                                    wisd);
-          }
+          return _elm_widget_item_signal_callback_list_get(item, l);
      }
 
-   return data;
+   return NULL;
 }
 
 EAPI void