summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Wedgbury <andrew.wedgbury@realvnc.com>2014-04-25 15:00:54 +0100
committerKristian Høgsberg <krh@bitplanet.net>2014-04-25 14:38:22 -0700
commit3e962728bf547de6316b5a01f40b38e55d3871cf (patch)
treedb4fd318c2d84a79aedf0cee7aff16400afbe12d
parent74df22befefa7e4ac2bd86ea0472347175b95ad1 (diff)
Use non-blocking timerfd to prevent blocking when updating timer event sources
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.
-rw-r--r--src/event-loop.c5
1 files 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);