[PATCH weston 1/8] libweston: Make weston_pointer destruction safe
Pekka Paalanen
ppaalanen at gmail.com
Wed Jan 31 11:22:09 UTC 2018
On Fri, 26 Jan 2018 18:47:55 +0200
Alexandros Frantzis <alexandros.frantzis at collabora.com> wrote:
> Properly clean up all sub-objects (e.g., weston_pointer_client objects)
> when a weston_pointer object is destroyed. The clean-up ensures that the
> server is able to safely handle client requests to any associated
> pointer resources, which, as a consenquence of a weston_pointer
> destruction, have now become inert.
>
> The clean-up involves, among other things, unsetting the destroyed
> weston_pointer object from the user data of pointer resources, and
> handling this NULL user data case where required.
>
> Signed-off-by: Alexandros Frantzis <alexandros.frantzis at collabora.com>
> ---
> libweston/input.c | 41 ++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 36 insertions(+), 5 deletions(-)
Hi Alexandros,
thank you for tackling these very old oversights.
> diff --git a/libweston/input.c b/libweston/input.c
> index 94a3423a..01f0d568 100644
> --- a/libweston/input.c
> +++ b/libweston/input.c
> @@ -105,6 +105,19 @@ weston_pointer_client_create(struct wl_client *client)
> static void
> weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
> {
> + struct wl_resource *resource;
> +
> + wl_resource_for_each(resource, &pointer_client->pointer_resources) {
> + wl_resource_set_user_data(resource, NULL);
> + }
> +
> + wl_resource_for_each(resource,
> + &pointer_client->relative_pointer_resources) {
> + wl_resource_set_user_data(resource, NULL);
> + }
> +
> + wl_list_remove(&pointer_client->pointer_resources);
> + wl_list_remove(&pointer_client->relative_pointer_resources);
> free(pointer_client);
> }
>
> @@ -170,11 +183,14 @@ unbind_pointer_client_resource(struct wl_resource *resource)
> struct wl_client *client = wl_resource_get_client(resource);
> struct weston_pointer_client *pointer_client;
>
> - pointer_client = weston_pointer_get_pointer_client(pointer, client);
> - assert(pointer_client);
> -
> wl_list_remove(wl_resource_get_link(resource));
> - weston_pointer_cleanup_pointer_client(pointer, pointer_client);
> +
> + if (pointer) {
> + pointer_client = weston_pointer_get_pointer_client(pointer,
> + client);
> + assert(pointer_client);
> + weston_pointer_cleanup_pointer_client(pointer, pointer_client);
> + }
> }
>
> static void unbind_resource(struct wl_resource *resource)
> @@ -1092,12 +1108,18 @@ weston_pointer_create(struct weston_seat *seat)
> WL_EXPORT void
> weston_pointer_destroy(struct weston_pointer *pointer)
> {
> + struct weston_pointer_client *pointer_client, *tmp;
> +
> wl_signal_emit(&pointer->destroy_signal, pointer);
>
> if (pointer->sprite)
> pointer_unmap_sprite(pointer);
>
> - /* XXX: What about pointer->resource_list? */
> + wl_list_for_each_safe(pointer_client, tmp, &pointer->pointer_clients,
> + link) {
> + wl_list_remove(&pointer_client->link);
> + weston_pointer_client_destroy(pointer_client);
> + }
>
> wl_list_remove(&pointer->focus_resource_listener.link);
> wl_list_remove(&pointer->focus_view_listener.link);
> @@ -2297,6 +2319,9 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
> struct weston_pointer *pointer = wl_resource_get_user_data(resource);
> struct weston_surface *surface = NULL;
>
> + if (!pointer)
> + return;
> +
Ideally if a wl_surface is provided, we would still do the role check
and assignment, but I see that would require quite some rearranging
here, so this is ok.
> if (surface_resource)
> surface = wl_resource_get_user_data(surface_resource);
>
> @@ -3674,6 +3699,9 @@ pointer_constraints_lock_pointer(struct wl_client *client,
> struct weston_region *region = region_resource ?
> wl_resource_get_user_data(region_resource) : NULL;
>
> + if (!pointer)
> + return;
This doesn't work, because the request is creating a new protocol
object. If you omit creating the zwp_locked_pointer_v1 protocol object
(wl_resource), it will lead to the client and server disagreeing on
what object ids are used and eventually to a fatal protocol error.
> +
> init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
> &zwp_locked_pointer_v1_interface,
> &locked_pointer_interface,
> @@ -4467,6 +4495,9 @@ pointer_constraints_confine_pointer(struct wl_client *client,
> struct weston_region *region = region_resource ?
> wl_resource_get_user_data(region_resource) : NULL;
>
> + if (!pointer)
> + return;
This one has the same problem as above.
Maybe we should have a patch before this one to make
init_pointer_constraint() deal with pointer=NULL?
> +
> init_pointer_constraint(resource, id, surface, pointer, region, lifetime,
> &zwp_confined_pointer_v1_interface,
> &confined_pointer_interface,
Otherwise this patch looks exactly correct.
Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20180131/35b0a8b9/attachment-0001.sig>
More information about the wayland-devel
mailing list