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); int __timeout);
libc_hidden_proto (__poll) libc_hidden_proto (__poll)
libc_hidden_proto (ppoll) 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 #endif

View File

@ -215,8 +215,7 @@ internal_nis_do_callback (struct dir_binding *bptr, netobj *cookie,
my_pollfd[i].revents = 0; my_pollfd[i].revents = 0;
} }
switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd, switch (i = __poll_noeintr (my_pollfd, svc_max_pollfd, 25*1000))
25*1000)))
{ {
case -1: case -1:
return NIS_CBERROR; return NIS_CBERROR;

View File

@ -53,29 +53,7 @@ wait_on_socket (int sock, long int usectmo)
struct pollfd fds[1]; struct pollfd fds[1];
fds[0].fd = sock; fds[0].fd = sock;
fds[0].events = POLLIN | POLLERR | POLLHUP; fds[0].events = POLLIN | POLLERR | POLLHUP;
int n = __poll (fds, 1, usectmo); return __poll_noeintr (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;
} }

View File

@ -378,9 +378,8 @@ send_again:
anyup = 0; anyup = 0;
for (;;) for (;;)
{ {
switch (__poll (&fd, 1, milliseconds)) switch (__poll_noeintr (&fd, 1, milliseconds))
{ {
case 0: case 0:
if (anyup == 0) if (anyup == 0)
{ {
@ -407,8 +406,6 @@ send_again:
* updated. * updated.
*/ */
case -1: case -1:
if (errno == EINTR)
continue;
cu->cu_error.re_errno = errno; cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV); 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.fd = ct->ct_sock;
fd.events = POLLIN; 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;
case 0: return -1;
ct->ct_error.re_status = RPC_TIMEDOUT;
return -1;
case -1: case -1:
if (errno == EINTR) ct->ct_error.re_status = RPC_CANTRECV;
continue; ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTRECV; return -1;
ct->ct_error.re_errno = errno;
return -1;
}
break;
} }
switch (len = __msgread (ct->ct_sock, buf, len)) 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); milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
fd.fd = s; fd.fd = s;
fd.events = POLLIN; fd.events = POLLIN;
do res = __poll_noeintr (&fd, 1, milliseconds);
res = __poll (&fd, 1, milliseconds);
while (res < 0 && errno == EINTR);
if (res <= 0) if (res <= 0)
{ {
if (res == 0) if (res == 0)

View File

@ -83,11 +83,9 @@ svc_run (void)
my_pollfd[i].revents = 0; my_pollfd[i].revents = 0;
} }
switch (i = __poll (my_pollfd, max_pollfd, -1)) switch (i = __poll_noeintr (my_pollfd, max_pollfd, -1))
{ {
case -1: case -1:
if (errno == EINTR)
continue;
perror (_("svc_run: - poll failed")); perror (_("svc_run: - poll failed"));
break; break;
case 0: case 0:

View File

@ -317,26 +317,19 @@ readtcp (char *xprtptr, char *buf, int len)
int milliseconds = 35 * 1000; int milliseconds = 35 * 1000;
struct pollfd pollfd; struct pollfd pollfd;
do pollfd.fd = sock;
pollfd.events = POLLIN;
switch (__poll_noeintr (&pollfd, 1, milliseconds))
{ {
pollfd.fd = sock; case -1:
pollfd.events = POLLIN; case 0:
switch (__poll (&pollfd, 1, milliseconds)) goto fatal_err;
{ default:
case -1: if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
if (errno == EINTR) || (pollfd.revents & POLLNVAL))
continue; goto fatal_err;
/*FALLTHROUGH*/ break;
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) if ((len = __read (sock, buf, len)) > 0)
return len; return len;

View File

@ -419,26 +419,19 @@ readunix (char *xprtptr, char *buf, int len)
int milliseconds = 35 * 1000; int milliseconds = 35 * 1000;
struct pollfd pollfd; struct pollfd pollfd;
do pollfd.fd = sock;
pollfd.events = POLLIN;
switch (__poll_noeintr (&pollfd, 1, milliseconds))
{ {
pollfd.fd = sock; case -1:
pollfd.events = POLLIN; case 0:
switch (__poll (&pollfd, 1, milliseconds)) goto fatal_err;
{ default:
case -1: if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
if (errno == EINTR) || (pollfd.revents & POLLNVAL))
continue; goto fatal_err;
/*FALLTHROUGH*/ break;
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) if ((len = __msgread (sock, buf, len)) > 0)
return len; return len;