discomfitor pushed a commit to branch enlightenment-0.20.

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

commit c9b720cccd280879c7f9a6b565ad5773c12f1efe
Author: Derek Foreman <der...@osg.samsung.com>
Date:   Wed Feb 17 13:11:04 2016 -0600

    Protect the wayland frame callback list from corruption
    
    The resource destroy callback for frame callbacks will walk the frame list
    to remove itself.  When freeing that list we need to make sure the
    resource destroy callback doesn't see the same list we're walking and
    corrupt it.
---
 src/bin/e_comp_wl.c | 16 ++++++++++++++--
 src/bin/e_pixmap.c  |  9 ++++++++-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index 802d25d..dca2dfb 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -981,8 +981,14 @@ _e_comp_wl_surface_state_finish(E_Comp_Wl_Surface_State 
*state)
 {
    struct wl_resource *cb;
    Eina_Rectangle *dmg;
+   Eina_List *free_list;
 
-   EINA_LIST_FREE(state->frames, cb)
+   /* The resource destroy callback will walk the state->frames list,
+    * so move the list to a temporary first.
+    */
+   free_list = state->frames;
+   state->frames = NULL;
+   EINA_LIST_FREE(free_list, cb)
      wl_resource_destroy(cb);
 
    EINA_LIST_FREE(state->damages, dmg)
@@ -2229,6 +2235,7 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client 
*ec)
    /* Eina_Rectangle *dmg; */
    struct wl_resource *cb;
    E_Client *subc;
+   Eina_List *free_list;
 
    /* make sure this is a wayland client */
    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
@@ -2247,7 +2254,12 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, 
E_Client *ec)
 
    _e_comp_wl_surface_state_finish(&ec->comp_data->pending);
 
-   EINA_LIST_FREE(ec->comp_data->frames, cb)
+   /* The resource destroy callback will walk the state->frames list,
+    * so move the list to a temporary first.
+    */
+   free_list = ec->comp_data->frames;
+   ec->comp_data->frames = NULL;
+   EINA_LIST_FREE(free_list, cb)
      wl_resource_destroy(cb);
 
    if (ec->comp_data->surface)
diff --git a/src/bin/e_pixmap.c b/src/bin/e_pixmap.c
index 8837bce..7f8bccb 100644
--- a/src/bin/e_pixmap.c
+++ b/src/bin/e_pixmap.c
@@ -635,10 +635,17 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
           {
              E_Comp_Wl_Client_Data *cd;
              struct wl_resource *cb;
+             Eina_List *free_list;
 
              if ((!cp->client) || (!cp->client->comp_data)) return;
              cd = (E_Comp_Wl_Client_Data *)cp->client->comp_data;
-             EINA_LIST_FREE(cd->frames, cb)
+
+             /* The destroy callback will remove items from the frame list
+              * so we move the list to a temporary before walking it here
+              */
+             free_list = cd->frames;
+             cd->frames = NULL;
+             EINA_LIST_FREE(free_list, cb)
                {
                   wl_callback_send_done(cb, ecore_time_unix_get() * 1000);
                   wl_resource_destroy(cb);

-- 


Reply via email to