diff options
author | Emre Ucan <eucan@de.adit-jv.com> | 2016-04-05 17:01:13 +0200 |
---|---|---|
committer | Wataru Natsume <wataru_natsume@xddp.denso.co.jp> | 2016-04-07 19:42:00 +0900 |
commit | 8d3db3d9a04e1c85ad4f0647cc48efd8150f5e7e (patch) | |
tree | e52b2852047f39b03aa50a270806ed5ce45f75ef | |
parent | ec05f5434dee2ace5320313054fc025be2530e37 (diff) | |
download | wayland-ivi-extension-8d3db3d9a04e1c85ad4f0647cc48efd8150f5e7e.tar.gz |
ivi-controller: wait clients before freeing ivilayer
We have to wait before freeing ivilayer that all clients destroy
their proxies. Otherwise, a client could send an event to the ivilayer
just after we destroyed it. This would cause a race condition and
potentially SEGV.
Furthermore, the layout_layer pointer of ivilayer set to NULL after
ivilayer freed in the old implementation. Therefore, old implementation
writes 4 bytes to invalid location. This implementation also solves the
invalid write problem by moving the free code.
Signed-off-by: Emre Ucan <eucan@de.adit-jv.com>
-rw-r--r-- | weston-ivi-shell/src/ivi-controller-impl.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/weston-ivi-shell/src/ivi-controller-impl.c b/weston-ivi-shell/src/ivi-controller-impl.c index 15e677e..49069c8 100644 --- a/weston-ivi-shell/src/ivi-controller-impl.c +++ b/weston-ivi-shell/src/ivi-controller-impl.c @@ -802,15 +802,22 @@ controller_layer_destroy(struct wl_client *client, { struct ivilayer *ivilayer = wl_resource_get_user_data(resource); (void)client; - (void)destroy_scene_object; - if (ivilayer->layout_layer != NULL) { - ivi_extension_layer_remove(ivilayer->shell, ivilayer->layout_layer); - ivilayer->layout_layer = NULL; - } + if (destroy_scene_object) { + if (ivilayer->layout_layer != NULL) { + ivi_extension_layer_remove(ivilayer->shell, ivilayer->layout_layer); + ivilayer->layout_layer = NULL; + } - wl_resource_destroy(resource); + wl_resource_destroy(resource); + if (wl_list_empty(&ivilayer->resource_list)) { + wl_list_remove(&ivilayer->link); + free(ivilayer); + } + } else { + wl_resource_destroy(resource); + } } static const @@ -1284,12 +1291,17 @@ layer_event_remove(struct ivi_layout_layer *layout_layer, return; } - wl_resource_for_each(resource, &ivilayer->resource_list) { + /*If there is no ivi_controller_layer objects, free + * ivilayer immediately. Otherwise wait for clients to destroy + * their proxies. */ + if (wl_list_empty(&ivilayer->resource_list)) { + wl_list_remove(&ivilayer->link); + free(ivilayer); + } else { + wl_resource_for_each(resource, &ivilayer->resource_list) { ivi_controller_layer_send_destroyed(resource); + } } - - wl_list_remove(&ivilayer->link); - free(ivilayer); } |