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.
This commit is contained in:
Derek Foreman 2016-02-17 13:11:04 -06:00 committed by Mike Blumenkrantz
parent e8c3320712
commit c9b720cccd
2 changed files with 22 additions and 3 deletions

View File

@ -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)

View File

@ -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);