[PATCH xserver 1/2] os: Delay freeing of epoll_wait return pointers until epoll is idle.
Peter Hutterer
peter.hutterer at who-t.net
Mon Aug 15 03:06:46 UTC 2016
On Sat, Aug 13, 2016 at 09:11:17AM -0700, Keith Packard wrote:
> Instead of freeing the struct ospollfd elements when the fd is
> removed by the user, delay that until epoll is idle so that we are
> sure no epoll_event structures could contain the stale pointer. This
> handles cases where an fd is removed from the ospoll callback
> interface, and also in case the OS keeps stale pointers around after
> the call to epoll_ctl with EPOLL_CTL_DEL.
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Cheers,
Peter
> ---
> os/ospoll.c | 25 +++++++++++++++++++++++--
> 1 file changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/os/ospoll.c b/os/ospoll.c
> index 3c2b80b..2996ac7 100644
> --- a/os/ospoll.c
> +++ b/os/ospoll.c
> @@ -54,6 +54,7 @@ struct ospollfd {
> enum ospoll_trigger trigger;
> void (*callback)(int fd, int xevents, void *data);
> void *data;
> + struct xorg_list deleted;
> };
>
> struct ospoll {
> @@ -61,6 +62,7 @@ struct ospoll {
> struct ospollfd **fds;
> int num;
> int size;
> + struct xorg_list deleted;
> };
>
> #endif
> @@ -115,6 +117,19 @@ ospoll_find(struct ospoll *ospoll, int fd)
> return -(lo + 1);
> }
>
> +#if EPOLL
> +static void
> +ospoll_clean_deleted(struct ospoll *ospoll)
> +{
> + struct ospollfd *osfd, *tmp;
> +
> + xorg_list_for_each_entry_safe(osfd, tmp, &ospoll->deleted, deleted) {
> + xorg_list_del(&osfd->deleted);
> + free(osfd);
> + }
> +}
> +#endif
> +
> /* Insert an element into an array
> *
> * base: base address of array
> @@ -160,6 +175,7 @@ ospoll_create(void)
> free (ospoll);
> return NULL;
> }
> + xorg_list_init(&ospoll->deleted);
> return ospoll;
> #endif
> #if POLL
> @@ -174,6 +190,7 @@ ospoll_destroy(struct ospoll *ospoll)
> if (ospoll) {
> assert (ospoll->num == 0);
> close(ospoll->epoll_fd);
> + ospoll_clean_deleted(ospoll);
> free(ospoll->fds);
> free(ospoll);
> }
> @@ -291,7 +308,9 @@ ospoll_remove(struct ospoll *ospoll, int fd)
>
> array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
> ospoll->num--;
> - free (osfd);
> + osfd->callback = NULL;
> + osfd->data = NULL;
> + xorg_list_add(&osfd->deleted, &ospoll->deleted);
> #endif
> #if POLL
> array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
> @@ -382,8 +401,10 @@ ospoll_wait(struct ospoll *ospoll, int timeout)
> if (revents & (~(EPOLLIN|EPOLLOUT)))
> xevents |= X_NOTIFY_ERROR;
>
> - osfd->callback(osfd->fd, xevents, osfd->data);
> + if (osfd->callback)
> + osfd->callback(osfd->fd, xevents, osfd->data);
> }
> + ospoll_clean_deleted(ospoll);
> #endif
> #if POLL
> nready = xserver_poll(ospoll->fds, ospoll->num, timeout);
> --
> 2.8.1
>
More information about the xorg-devel
mailing list