From c4c957428941f2b8b4160136ae6e98a6ad04055e Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Wed, 25 Sep 2013 16:41:12 +0900 Subject: [PATCH] elm_widget: fix widget signal callback memory leak. Thanks to bluezery D228 for pointing out the issue. --- src/lib/elm_widget.c | 80 ++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index ca3d375..77b8700 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -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 -- 2.7.4