raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=ac10a00acc6bacf01bfd208cc78b4eb2a6a925d8

commit ac10a00acc6bacf01bfd208cc78b4eb2a6a925d8
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Tue Jul 19 15:42:10 2016 +0900

    evas - on shutdown avoid potential invalid memory access
    
    i don't know for sure if this fixes T4103 but in theory i think it
    might given a reading of the backtrace and a guess at what might
    happen, so try this fix. it doesn't hurt and can only help.
    
    @fix
---
 src/lib/evas/canvas/evas_layer.c        | 48 +++++++++++++++++++++++++++------
 src/lib/evas/canvas/evas_object_image.c |  6 +++++
 src/lib/evas/canvas/evas_render.c       |  3 +++
 src/lib/evas/include/evas_private.h     |  3 +++
 4 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/src/lib/evas/canvas/evas_layer.c b/src/lib/evas/canvas/evas_layer.c
index 12c8b2f..b81c0e0 100644
--- a/src/lib/evas/canvas/evas_layer.c
+++ b/src/lib/evas/canvas/evas_layer.c
@@ -33,19 +33,25 @@ void
 evas_object_release(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, int 
clean_layer)
 {
    if (!obj->in_layer) return;
-   obj->layer->objects = (Evas_Object_Protected_Data 
*)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects), 
EINA_INLIST_GET(obj));
+   if (!obj->layer->walking_objects)
+     obj->layer->objects = (Evas_Object_Protected_Data 
*)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects), 
EINA_INLIST_GET(obj));
    eo_data_unref(eo_obj, obj);
-   obj->layer->usage--;
-   if (clean_layer)
+   if (!obj->layer->walking_objects)
      {
-        if (obj->layer->usage <= 0)
+        obj->layer->usage--;
+        if (clean_layer)
           {
-             evas_layer_del(obj->layer);
-             _evas_layer_free(obj->layer);
+             if (obj->layer->usage <= 0)
+               {
+                  evas_layer_del(obj->layer);
+                  _evas_layer_free(obj->layer);
+               }
           }
+        obj->layer = NULL;
+        obj->in_layer = 0;
      }
-   obj->layer = NULL;
-   obj->in_layer = 0;
+   else
+     obj->layer->removes = eina_list_append(obj->layer->removes, obj);
 }
 
 Evas_Layer *
@@ -67,15 +73,41 @@ _evas_layer_free(Evas_Layer *lay)
 }
 
 void
+_evas_layer_flush_removes(Evas_Layer *lay)
+{
+   if (lay->walking_objects) return;
+   while (lay->removes)
+     {
+        Evas_Object_Protected_Data *obj = lay->removes->data;
+
+        lay->objects = (Evas_Object_Protected_Data *)
+          eina_inlist_remove(EINA_INLIST_GET(lay->objects),
+                             EINA_INLIST_GET(obj));
+        lay->removes = eina_list_remove_list(lay->removes, lay->removes);
+        obj->layer = NULL;
+        obj->in_layer = 0;
+        lay->usage--;
+     }
+   if (lay->usage <= 0)
+     {
+        evas_layer_del(lay);
+        _evas_layer_free(lay);
+     }
+}
+
+void
 evas_layer_pre_free(Evas_Layer *lay)
 {
    Evas_Object_Protected_Data *obj;
 
+   lay->walking_objects++;
    EINA_INLIST_FOREACH(lay->objects, obj)
      {
         if ((!obj->smart.parent) && (!obj->delete_me))
           evas_object_del(obj->object);
      }
+   lay->walking_objects--;
+   _evas_layer_flush_removes(lay);
 }
 
 void
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index 8ba756d..ad7810a 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -1134,6 +1134,7 @@ _evas_canvas_image_cache_reload(Eo *eo_e, 
Evas_Public_Data *e)
      {
         Evas_Object_Protected_Data *obj;
 
+        layer->walking_objects++;
         EINA_INLIST_FOREACH(layer->objects, obj)
           {
              if (eo_isa(obj->object, MY_CLASS))
@@ -1142,12 +1143,15 @@ _evas_canvas_image_cache_reload(Eo *eo_e, 
Evas_Public_Data *e)
                   evas_object_inform_call_image_unloaded(obj->object);
                }
           }
+        layer->walking_objects--;
+        _evas_layer_flush_removes(layer);
      }
    evas_image_cache_flush(eo_e);
    EINA_INLIST_FOREACH(e->layers, layer)
      {
         Evas_Object_Protected_Data *obj;
 
+        layer->walking_objects++;
         EINA_INLIST_FOREACH(layer->objects, obj)
           {
              if (eo_isa(obj->object, MY_CLASS))
@@ -1158,6 +1162,8 @@ _evas_canvas_image_cache_reload(Eo *eo_e, 
Evas_Public_Data *e)
                   evas_object_change(obj->object, obj);
                }
           }
+        layer->walking_objects--;
+        _evas_layer_flush_removes(layer);
      }
    evas_image_cache_flush(eo_e);
 }
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index cf34a82..5aa5d38 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -3300,6 +3300,7 @@ _evas_canvas_render_dump(Eo *eo_e, Evas_Public_Data *e)
           {
              Evas_Object_Protected_Data *obj;
 
+             lay->walking_objects++;
              EINA_INLIST_FOREACH(lay->objects, obj)
                {
                   if (obj->proxy->surface)
@@ -3324,6 +3325,8 @@ _evas_canvas_render_dump(Eo *eo_e, Evas_Public_Data *e)
                     evas_object_inform_call_image_unloaded(obj->object);
                   _evas_render_dump_map_surfaces(obj->object);
                }
+             lay->walking_objects--;
+             _evas_layer_flush_removes(lay);
           }
         if ((e->engine.func) && (e->engine.func->output_dump) &&
             (e->engine.data.output))
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 684edfc..474a66e 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -924,7 +924,9 @@ struct _Evas_Layer
    Evas_Public_Data *evas;
 
    void             *engine_data;
+   Eina_List        *removes;
    int               usage;
+   int               walking_objects;
    unsigned char     delete_me : 1;
 };
 
@@ -1532,6 +1534,7 @@ void evas_rects_return_difference_rects(Eina_Array 
*rects, int x, int y, int w,
 void evas_object_clip_dirty(Evas_Object *obj, Evas_Object_Protected_Data *pd);
 void evas_object_recalc_clippees(Evas_Object_Protected_Data *pd);
 Evas_Layer *evas_layer_new(Evas *e);
+void _evas_layer_flush_removes(Evas_Layer *lay);
 void evas_layer_pre_free(Evas_Layer *lay);
 void evas_layer_free_objects(Evas_Layer *lay);
 void evas_layer_clean(Evas *e);

-- 


Reply via email to