[PATCH wayland] Use non-blocking timerfd to prevent blocking when updating timer event sources
Kristian Høgsberg
hoegsberg at gmail.com
Fri Apr 25 14:39:26 PDT 2014
On Fri, Apr 25, 2014 at 03:00:54PM +0100, Andrew Wedgbury wrote:
> This implements a simple fix for the blocking problem that occurs when
> updating a timer event source after the timer expires, but before its
> callback is dispatched. This can happen when another event happens during the
> same epoll wakeup as the timer event, and causes the read() call in
> wl_event_source_timer_dispatch() to block for the updated duration of the
> timer.
>
> We never want this read() call to block, so I believe it makes sense for the
> timerfd to be non-blocking, and we simply ignore the case where the read fails
> with EAGAIN. We still report all other errors as before, and still ignore the
> actual value read from the socket.
>
> With this change, the event_loop_timer_updates unit test case I submitted
> previously now passes, and weston appears to work as before.
Thanks, Andrew, good test case and analysis and I agree with the fix.
Test case and fix committed.
Kristian
>
> ---
> src/event-loop.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/src/event-loop.c b/src/event-loop.c
> index d323601..1046600 100644
> --- a/src/event-loop.c
> +++ b/src/event-loop.c
> @@ -173,7 +173,7 @@ wl_event_source_timer_dispatch(struct wl_event_source *source,
> int len;
>
> len = read(source->fd, &expires, sizeof expires);
> - if (len != sizeof expires)
> + if (!(len == -1 && errno == EAGAIN) && len != sizeof expires)
> /* Is there anything we can do here? Will this ever happen? */
> fprintf(stderr, "timerfd read error: %m\n");
>
> @@ -196,7 +196,8 @@ wl_event_loop_add_timer(struct wl_event_loop *loop,
> return NULL;
>
> source->base.interface = &timer_source_interface;
> - source->base.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
> + source->base.fd = timerfd_create(CLOCK_MONOTONIC,
> + TFD_CLOEXEC | TFD_NONBLOCK);
> source->func = func;
>
> return add_source(loop, &source->base, WL_EVENT_READABLE, data);
> --
> 1.9.2
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list