From 4ff82885e8d3d95f360f72a91e453d61ba93defa Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sat, 24 Nov 2012 04:22:21 +0000 Subject: [PATCH] delay e_win and e_popup deletes to avoid bad mem accesses from objects/callbacks that free evases deep inside a callback tree. :) SVN revision: 79622 --- src/bin/e_object.c | 26 ++++++++++++++++++++++++++ src/bin/e_object.h | 3 +++ src/bin/e_popup.c | 1 + src/bin/e_win.c | 1 + 4 files changed, 31 insertions(+) diff --git a/src/bin/e_object.c b/src/bin/e_object.c index 90958f125..2210dc98f 100644 --- a/src/bin/e_object.c +++ b/src/bin/e_object.c @@ -26,17 +26,43 @@ e_object_alloc(int size, int type, E_Object_Cleanup_Func cleanup_func) return obj; } +static void +_delay_del(void *data) +{ + E_Object *obj = data; + + obj->delay_del_job = NULL; + if (obj->del_att_func) obj->del_att_func(obj); + if (obj->del_func) obj->del_func(obj); + e_object_unref(obj); +} + EAPI void e_object_del(E_Object *obj) { E_OBJECT_CHECK(obj); if (obj->deleted) return; + if (obj->del_delay_func) + { + obj->del_delay_func(obj); + if (!obj->delay_del_job) + obj->delay_del_job = ecore_job_add(_delay_del, obj); + obj->deleted = 1; + return; + } obj->deleted = 1; if (obj->del_att_func) obj->del_att_func(obj); if (obj->del_func) obj->del_func(obj); e_object_unref(obj); } +EAPI void +e_object_delay_del_set(E_Object *obj, void *func) +{ + E_OBJECT_CHECK(obj); + obj->del_delay_func = func; +} + EAPI int e_object_is_del(E_Object *obj) { diff --git a/src/bin/e_object.h b/src/bin/e_object.h index 071ac7a84..97a4ebad6 100644 --- a/src/bin/e_object.h +++ b/src/bin/e_object.h @@ -63,8 +63,10 @@ struct _E_Object E_Object_Cleanup_Func cleanup_func; E_Object_Cleanup_Func free_att_func; E_Object_Cleanup_Func del_att_func; + E_Object_Cleanup_Func del_delay_func; Eina_Inlist *del_fn_list; void *data; + Ecore_Job *delay_del_job; int walking_list; Eina_Bool deleted : 1; }; @@ -80,6 +82,7 @@ struct _E_Object_Delfn EAPI void *e_object_alloc (int size, int type, E_Object_Cleanup_Func cleanup_func); EAPI void e_object_del (E_Object *obj); +EAPI void e_object_delay_del_set (E_Object *obj, void *func); EAPI int e_object_is_del (E_Object *obj); EAPI void e_object_del_func_set (E_Object *obj, E_Object_Cleanup_Func del_func); EAPI void e_object_type_set (E_Object *obj, int type); diff --git a/src/bin/e_popup.c b/src/bin/e_popup.c index 89b51d14d..e2210ad46 100644 --- a/src/bin/e_popup.c +++ b/src/bin/e_popup.c @@ -41,6 +41,7 @@ e_popup_new(E_Zone *zone, int x, int y, int w, int h) pop = E_OBJECT_ALLOC(E_Popup, E_POPUP_TYPE, _e_popup_free); if (!pop) return NULL; + e_object_delay_del_set(E_OBJECT(pop), e_popup_hide); pop->zone = zone; pop->zx = pop->zone->x; pop->zy = pop->zone->y; diff --git a/src/bin/e_win.c b/src/bin/e_win.c index 16eb3f2be..3dbf2c9c9 100644 --- a/src/bin/e_win.c +++ b/src/bin/e_win.c @@ -215,6 +215,7 @@ e_win_new(E_Container *con) win = E_OBJECT_ALLOC(E_Win, E_WIN_TYPE, _e_win_free); if (!win) return NULL; e_object_del_func_set(E_OBJECT(win), _e_win_del); + e_object_delay_del_set(E_OBJECT(win), e_win_hide); win->container = con; win->ecore_evas = e_canvas_new(con->manager->root, 0, 0, 1, 1, 1, 0,