[PATCH wayland v4 08/11] client: Replace the singleton zombie with bespoke zombies
Derek Foreman
derekf at osg.samsung.com
Wed Jan 3 22:25:18 UTC 2018
On 2017-12-28 01:53 PM, Daniel Stone wrote:
> From: Derek Foreman <derekf at osg.samsung.com>
>
> Using the singleton zombie object doesn't allow us to posthumously retain
> object interface information, which makes it difficult to properly inter
> future events destined for the recently deceased proxy.
>
> Notably, this makes it impossible for zombie proxy destined file
> descriptors to be properly consumed.
>
> When we create a proxy, we now create a zombie-state object to hold
> information about the file descriptors in events it can receive. This
> will allow us, in a future patch, to close those FDs.
>
> [daniels: Split Derek's patch into a few smaller ones.]
>
> Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
> Reviewed-by: Daniel Stone <daniels at collabora.com>
> Signed-off-by: Daniel Stone <daniels at collabora.com>
> ---
> src/wayland-client.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 78 insertions(+), 4 deletions(-)
>
> diff --git a/src/wayland-client.c b/src/wayland-client.c
> index 987418a1..62d4f222 100644
> --- a/src/wayland-client.c
> +++ b/src/wayland-client.c
> @@ -55,6 +55,11 @@ enum wl_proxy_flag {
> WL_PROXY_FLAG_WRAPPER = (1 << 2),
> };
>
> +struct wl_zombie {
> + int event_count;
> + int *fd_count;
> +};
> +
> struct wl_proxy {
> struct wl_object object;
> struct wl_display *display;
> @@ -350,6 +355,66 @@ wl_display_create_queue(struct wl_display *display)
> return queue;
> }
>
> +static int
> +message_count_fds(const char *signature)
> +{
> + unsigned int count, i, fds = 0;
> + struct argument_details arg;
> +
> + count = arg_count_for_signature(signature);
> + for (i = 0; i < count; i++) {
> + signature = get_next_argument(signature, &arg);
> + if (arg.type == 'h')
> + fds++;
> + }
> +
> + return fds;
> +}
> +
> +static struct wl_zombie *
> +prepare_zombie(struct wl_proxy *proxy)
> +{
> + const struct wl_interface *interface = proxy->object.interface;
> + const struct wl_message *message;
> + int i, count;
> + struct wl_zombie *zombie = NULL;
> +
> + /* If we hit an event with an FD, ensure we have a zombie object and
> + * fill the fd_count slot for that event with the number of FDs for
> + * that event. Interfaces with no events containing FDs will not have
> + * zombie objects created. */
> + for (i = 0; i < interface->event_count; i++) {
> + message = &interface->events[i];
> + count = message_count_fds(message->signature);
> +
> + if (!count)
> + continue;
> +
> + if (!zombie) {
> + zombie = zalloc(sizeof(*zombie) +
> + (interface->event_count * sizeof(int)));
> + if (!zombie)
> + return NULL;
> +
> + zombie->event_count = interface->event_count;
> + zombie->fd_count = (int *) &zombie[1];
> + }
> +
> + zombie->fd_count[i] = count;
> + }
> +
> + return zombie;
> +}
> +
> +static enum wl_iterator_result
> +free_zombies(void *element, void *data, uint32_t flags)
> +{
> + if (flags & WL_MAP_ENTRY_ZOMBIE)
> + free(element);
> +
> + return WL_ITERATOR_CONTINUE;
> +}
> +
> static struct wl_proxy *
> proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
> uint32_t version)
> @@ -434,10 +499,14 @@ proxy_destroy(struct wl_proxy *proxy)
> if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) {
> wl_map_remove(&proxy->display->objects, proxy->object.id);
> } else if (proxy->object.id < WL_SERVER_ID_START) {
> + struct wl_zombie *zombie = prepare_zombie(proxy);
I think we discussed this on irc and I said this patch was ok, but I
missed this change...
prepare_zombie(proxy) should probably only be called from
wl_proxy_create and create_for_id - calling it in the destroy path
results in a malloc() call during deleting.
Should the malloc() fail and we can't actually allocate the zombie at
during deletion we're going to have a problem.
Otherwise, I like the way you've split up the series, and I've reviewed
your new patches.
Thanks,
Derek
> +
> + /* The map now contains the zombie entry, until the delete_id
> + * event arrives. */
> wl_map_insert_at(&proxy->display->objects,
> WL_MAP_ENTRY_ZOMBIE,
> proxy->object.id,
> - NULL);
> + zombie);
> } else {
> wl_map_insert_at(&proxy->display->objects, 0,
> proxy->object.id, NULL);
> @@ -860,12 +929,16 @@ display_handle_delete_id(void *data, struct wl_display *display, uint32_t id)
>
> proxy = wl_map_lookup(&display->objects, id);
>
> - if (wl_object_is_zombie(&display->objects, id))
> + if (wl_object_is_zombie(&display->objects, id)) {
> + /* For zombie objects, the 'proxy' is actually the zombie
> + * event-information structure, which we can free. */
> + free(proxy);
> wl_map_remove(&display->objects, id);
> - else if (proxy)
> + } else if (proxy) {
> proxy->flags |= WL_PROXY_FLAG_ID_DELETED;
> - else
> + } else {
> wl_log("error: received delete_id for unknown id (%u)\n", id);
> + }
>
> pthread_mutex_unlock(&display->mutex);
> }
> @@ -1087,6 +1160,7 @@ WL_EXPORT void
> wl_display_disconnect(struct wl_display *display)
> {
> wl_connection_destroy(display->connection);
> + wl_map_for_each(&display->objects, free_zombies, NULL);
> wl_map_release(&display->objects);
> wl_event_queue_release(&display->default_queue);
> wl_event_queue_release(&display->display_queue);
>
More information about the wayland-devel
mailing list