discomfitor pushed a commit to branch enlightenment-0.20. http://git.enlightenment.org/core/enlightenment.git/commit/?id=c9b720cccd280879c7f9a6b565ad5773c12f1efe
commit c9b720cccd280879c7f9a6b565ad5773c12f1efe Author: Derek Foreman <[email protected]> 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); --
