summaryrefslogtreecommitdiff
path: root/src/lib/eo
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2017-02-16 13:37:16 -0800
committerCedric BAIL <cedric@osg.samsung.com>2017-02-16 13:37:19 -0800
commitae8004033112f0f4f94ad6d0eac2f010b5c009cd (patch)
tree94ef267acd5bbd29bf6ba075c8255140e489b362 /src/lib/eo
parent7760613107f164f14e706deb96c0ae9ac6614417 (diff)
eo: ensure the generation is correctly clamped
Summary: when a few recursive event emissions are happening, and in some deep recursive level a subscription to the same object is happening, the subscription would just be executed when the complete recursion is done. that is wrong. The subscription needs to be executed when the event is called after the subscription is added, undepended from any recursive level. That fixes that and adds a regression test for it. This was discovered in e, since e gives a lot of error messages about a eo object that is already freed. It turned out this object is returned from evas, and exactly the above happened to the EFL_EVENT_DEL subscription of that object. Test Plan: make check Reviewers: tasn, cedric, stefan_schmidt Subscribers: stefan_schmidt, netstar, zmike, raster, jpeg Differential Revision: https://phab.enlightenment.org/D4656 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
Diffstat (limited to 'src/lib/eo')
-rw-r--r--src/lib/eo/eo_base_class.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 2f3803aab9..c6b4775b0a 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -1062,20 +1062,42 @@ _eo_callbacks_clear(Efl_Object_Data *pd)
1062{ 1062{
1063 Eo_Callback_Description **itr; 1063 Eo_Callback_Description **itr;
1064 unsigned int i = 0; 1064 unsigned int i = 0;
1065 Eina_Bool remove_callbacks;
1066 unsigned int generation_clamp;
1065 1067
1066 /* If there are no deletions waiting. */ 1068 /* If there are no deletions waiting. */
1067 if (!pd->need_cleaning) return; 1069 if (!pd->need_cleaning) return;
1068 /* Abort if we are currently walking the list. */
1069 if (pd->event_frame) return;
1070 1070
1071 pd->need_cleaning = EINA_FALSE; 1071
1072 if (pd->event_frame)
1073 {
1074 /* there is still a event emission going on ... do not delete anything! */
1075 remove_callbacks = EINA_FALSE;
1076 /* if we are in event subscription we need to clamp the generations at the current frame otherwise we are possiblity not executing that later */
1077 generation_clamp = pd->event_frame->generation;
1078 }
1079 else
1080 {
1081 /* no event emission running */
1082 /* remove deleted callbacks */
1083 remove_callbacks = EINA_TRUE;
1084 /* clap to 0 generation */
1085 generation_clamp = 0;
1086 /* we dont need to clean later */
1087 pd->need_cleaning = EINA_FALSE;
1088 }
1089
1072 while (i < pd->callbacks_count) 1090 while (i < pd->callbacks_count)
1073 { 1091 {
1074 itr = pd->callbacks + i; 1092 itr = pd->callbacks + i;
1075 if ((*itr)->delete_me) _eo_callback_remove(pd, itr); 1093 if (remove_callbacks && (*itr)->delete_me)
1094 {
1095 _eo_callback_remove(pd, itr);
1096 }
1076 else 1097 else
1077 { 1098 {
1078 (*itr)->generation = 0; 1099 if ((*itr)->generation > generation_clamp)
1100 (*itr)->generation = generation_clamp;
1079 i++; 1101 i++;
1080 } 1102 }
1081 } 1103 }