[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