From c83b8a87170cda275a5c591fe2a1d3657d2a6711 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 3 Nov 2014 18:51:39 -0200 Subject: [PATCH] introduce internal function to ease poll retry with timeout --- include/sys/poll.h | 42 +++++++++++++++++++++++++++++++++++++++++- nis/nis_callback.c | 3 +-- nscd/nscd_helper.c | 24 +----------------------- sunrpc/clnt_udp.c | 5 +---- sunrpc/clnt_unix.c | 22 ++++++++-------------- sunrpc/rtime.c | 4 +--- sunrpc/svc_run.c | 4 +--- sunrpc/svc_tcp.c | 29 +++++++++++------------------ sunrpc/svc_unix.c | 29 +++++++++++------------------ 9 files changed, 76 insertions(+), 86 deletions(-) diff --git a/include/sys/poll.h b/include/sys/poll.h index a42bc93873..49169b02b2 100644 --- a/include/sys/poll.h +++ b/include/sys/poll.h @@ -6,6 +6,46 @@ extern int __poll (struct pollfd *__fds, unsigned long int __nfds, int __timeout); libc_hidden_proto (__poll) libc_hidden_proto (ppoll) -#endif + +#include +#include + +static inline int +__poll_noeintr (struct pollfd *__fds, unsigned long int __nfds, + int __timeout) +{ + int __ret = __poll (__fds, __nfds, __timeout); + + if (__ret == -1 && __glibc_unlikely (errno == EINTR)) + { + /* Handle the case where the poll() call is interrupted by a + signal. We cannot just use TEMP_FAILURE_RETRY since it might + lead to infinite loops. We can't tell how long poll has + already waited, and we can't assume the existence of a + higher-precision clock, but that's ok-ish: the timeout is a + lower bound, we just have to make sure we don't wait + indefinitely. */ + struct timeval __now; + (void) __gettimeofday (&__now, NULL); + + long int __end = __now.tv_sec * 1000 + __timeout + + (__now.tv_usec + 500) / 1000; + + while (1) + { + __ret = __poll (__fds, __nfds, __timeout); + if (__ret != -1 || errno != EINTR) + break; + + /* Recompute the timeout time. */ + (void) __gettimeofday (&__now, NULL); + __timeout = __end - __now.tv_sec * 1000 + - (__now.tv_usec + 500) / 1000; + } + } + + return __ret; +} +#endif /* _ISOMAC */ #endif diff --git a/nis/nis_callback.c b/nis/nis_callback.c index e3527339a7..baa8d755c3 100644 --- a/nis/nis_callback.c +++ b/nis/nis_callback.c @@ -215,8 +215,7 @@ internal_nis_do_callback (struct dir_binding *bptr, netobj *cookie, my_pollfd[i].revents = 0; } - switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd, - 25*1000))) + switch (i = __poll_noeintr (my_pollfd, svc_max_pollfd, 25*1000)) { case -1: return NIS_CBERROR; diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index ee3b67f03d..fe5f096a8a 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -53,29 +53,7 @@ wait_on_socket (int sock, long int usectmo) struct pollfd fds[1]; fds[0].fd = sock; fds[0].events = POLLIN | POLLERR | POLLHUP; - int n = __poll (fds, 1, usectmo); - if (n == -1 && __builtin_expect (errno == EINTR, 0)) - { - /* Handle the case where the poll() call is interrupted by a - signal. We cannot just use TEMP_FAILURE_RETRY since it might - lead to infinite loops. */ - struct timeval now; - (void) __gettimeofday (&now, NULL); - long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000; - long int timeout = usectmo; - while (1) - { - n = __poll (fds, 1, timeout); - if (n != -1 || errno != EINTR) - break; - - /* Recompute the timeout time. */ - (void) __gettimeofday (&now, NULL); - timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000); - } - } - - return n; + return __poll_noeintr (fds, 1, usectmo); } diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c index 6ffa5f2590..f1e6500fa0 100644 --- a/sunrpc/clnt_udp.c +++ b/sunrpc/clnt_udp.c @@ -378,9 +378,8 @@ send_again: anyup = 0; for (;;) { - switch (__poll (&fd, 1, milliseconds)) + switch (__poll_noeintr (&fd, 1, milliseconds)) { - case 0: if (anyup == 0) { @@ -407,8 +406,6 @@ send_again: * updated. */ case -1: - if (errno == EINTR) - continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } diff --git a/sunrpc/clnt_unix.c b/sunrpc/clnt_unix.c index 32d88b9425..aff6fa50df 100644 --- a/sunrpc/clnt_unix.c +++ b/sunrpc/clnt_unix.c @@ -551,22 +551,16 @@ readunix (char *ctptr, char *buf, int len) fd.fd = ct->ct_sock; fd.events = POLLIN; - while (TRUE) + switch (__poll_noeintr (&fd, 1, milliseconds)) { - switch (__poll (&fd, 1, milliseconds)) - { - case 0: - ct->ct_error.re_status = RPC_TIMEDOUT; - return -1; + case 0: + ct->ct_error.re_status = RPC_TIMEDOUT; + return -1; - case -1: - if (errno == EINTR) - continue; - ct->ct_error.re_status = RPC_CANTRECV; - ct->ct_error.re_errno = errno; - return -1; - } - break; + case -1: + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = errno; + return -1; } switch (len = __msgread (ct->ct_sock, buf, len)) { diff --git a/sunrpc/rtime.c b/sunrpc/rtime.c index d224624f8b..79d55d1415 100644 --- a/sunrpc/rtime.c +++ b/sunrpc/rtime.c @@ -102,9 +102,7 @@ rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); fd.fd = s; fd.events = POLLIN; - do - res = __poll (&fd, 1, milliseconds); - while (res < 0 && errno == EINTR); + res = __poll_noeintr (&fd, 1, milliseconds); if (res <= 0) { if (res == 0) diff --git a/sunrpc/svc_run.c b/sunrpc/svc_run.c index 90dfc94056..5e20aaecfb 100644 --- a/sunrpc/svc_run.c +++ b/sunrpc/svc_run.c @@ -83,11 +83,9 @@ svc_run (void) my_pollfd[i].revents = 0; } - switch (i = __poll (my_pollfd, max_pollfd, -1)) + switch (i = __poll_noeintr (my_pollfd, max_pollfd, -1)) { case -1: - if (errno == EINTR) - continue; perror (_("svc_run: - poll failed")); break; case 0: diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c index 913f05f033..92886f0869 100644 --- a/sunrpc/svc_tcp.c +++ b/sunrpc/svc_tcp.c @@ -317,26 +317,19 @@ readtcp (char *xprtptr, char *buf, int len) int milliseconds = 35 * 1000; struct pollfd pollfd; - do + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (__poll_noeintr (&pollfd, 1, milliseconds)) { - pollfd.fd = sock; - pollfd.events = POLLIN; - switch (__poll (&pollfd, 1, milliseconds)) - { - case -1: - if (errno == EINTR) - continue; - /*FALLTHROUGH*/ - case 0: - goto fatal_err; - default: - if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) - || (pollfd.revents & POLLNVAL)) - goto fatal_err; - break; - } + case -1: + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; } - while ((pollfd.revents & POLLIN) == 0); if ((len = __read (sock, buf, len)) > 0) return len; diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c index 963276b2f9..6d93c5f6e5 100644 --- a/sunrpc/svc_unix.c +++ b/sunrpc/svc_unix.c @@ -419,26 +419,19 @@ readunix (char *xprtptr, char *buf, int len) int milliseconds = 35 * 1000; struct pollfd pollfd; - do + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (__poll_noeintr (&pollfd, 1, milliseconds)) { - pollfd.fd = sock; - pollfd.events = POLLIN; - switch (__poll (&pollfd, 1, milliseconds)) - { - case -1: - if (errno == EINTR) - continue; - /*FALLTHROUGH*/ - case 0: - goto fatal_err; - default: - if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) - || (pollfd.revents & POLLNVAL)) - goto fatal_err; - break; - } + case -1: + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; } - while ((pollfd.revents & POLLIN) == 0); if ((len = __msgread (sock, buf, len)) > 0) return len;