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
parent 6f3e670f75
commit 6a65d2a546
2 changed files with 22 additions and 3 deletions

View File

@ -980,8 +980,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)
@ -2118,6 +2124,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;
@ -2136,7 +2143,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);