introduce internal function to ease poll retry with timeout

This commit is contained in:
Alexandre Oliva 2014-11-03 18:51:39 -02:00
parent ab97ee8f1b
commit c83b8a8717
9 changed files with 76 additions and 86 deletions

View File

@ -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 <errno.h>
#include <sys/time.h>
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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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))
{

View File

@ -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)

View File

@ -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:

View File

@ -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;

View File

@ -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;