From df92a13a270bea95f5c5260ee5de0c5b776f5131 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Tue, 2 Nov 2021 10:10:01 -0700 Subject: [PATCH] util/libsync: Fix timeout handling if poll() wakes up early Check how long poll waited, and use a smaller timeout on the next iteration through the loop. Reviewed-by: Jason Ekstrand Part-of: --- src/util/libsync.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/util/libsync.h b/src/util/libsync.h index 1c9303c174a..0cb895a75d3 100644 --- a/src/util/libsync.h +++ b/src/util/libsync.h @@ -36,6 +36,7 @@ #include #include #include +#include #if defined(__cplusplus) extern "C" { @@ -102,12 +103,15 @@ static inline int sync_wait(int fd, int timeout) { struct pollfd fds = {0}; int ret; + struct timespec poll_start, poll_end; fds.fd = fd; fds.events = POLLIN; do { + clock_gettime(CLOCK_MONOTONIC, &poll_start); ret = poll(&fds, 1, timeout); + clock_gettime(CLOCK_MONOTONIC, &poll_end); if (ret > 0) { if (fds.revents & (POLLERR | POLLNVAL)) { errno = EINVAL; @@ -118,6 +122,8 @@ static inline int sync_wait(int fd, int timeout) errno = ETIME; return -1; } + timeout -= (poll_end.tv_sec - poll_start.tv_sec) * 1000 + + (poll_end.tv_nsec - poll_end.tv_nsec) / 1000000; } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); return ret;