@@ -9,10 +9,10 @@ Version 2.21
* The following bugs are resolved with this release:
- 6652, 12926, 14132, 14138, 14171, 14498, 15215, 15884, 17266, 17344,
- 17363, 17370, 17371, 17411, 17460, 17475, 17485, 17501, 17506, 17508,
- 17522, 17555, 17570, 17571, 17572, 17573, 17574, 17582, 17583, 17584,
- 17585, 17589.
+ 6652, 12926, 14132, 14138, 14171, 14498, 15215, 15819, 15884, 17266,
+ 17344, 17363, 17370, 17371, 17411, 17460, 17475, 17485, 17501, 17506,
+ 17508, 17522, 17555, 17570, 17571, 17572, 17573, 17574, 17582, 17583,
+ 17584, 17585, 17589.
* New locales: tu_IN, bh_IN.
@@ -6,6 +6,67 @@ 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 <time.h>
+
+static inline int
+__poll_noeintr (struct pollfd *__fds, unsigned long int __nfds,
+ int __timeout)
+{
+ int __ret;
+
+ __retry_poll:
+ __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 timespec __tscur, __tsend;
+ /* Remember which clock to use. */
+ static clockid_t __xclk = CLOCK_MONOTONIC;
+ clockid_t __clk = __xclk;
+
+ __try_another_clock:
+ if (__glibc_unlikely (__clock_gettime (__clk, &__tscur) == -1))
+ {
+ if (errno == EINVAL && __clk == CLOCK_MONOTONIC)
+ {
+ __xclk = __clk = CLOCK_REALTIME;
+ goto __try_another_clock;
+ }
+
+ /* At least CLOCK_REALTIME should always be supported, but
+ if clock_gettime fails for any other reason, the best we
+ can do is to retry with a slightly lower timeout, until
+ we complete without interruption. */
+ __timeout--;
+ goto __retry_poll;
+ }
+
+ __tsend.tv_sec = __tscur.tv_sec + __timeout / 1000;
+ __tsend.tv_nsec = __tscur.tv_nsec + __timeout % 1000 * 1000000L + 500000;
+
+ while (1)
+ {
+ __ret = __poll (__fds, __nfds,
+ (__tsend.tv_sec - __tscur.tv_sec) * 1000
+ + (__tsend.tv_nsec - __tscur.tv_nsec) / 1000000);
+ if (__ret != -1 || errno != EINTR)
+ break;
+
+ (void) __clock_gettime (__clk, &__tscur);
+ }
+ }
+
+ return __ret;
+}
+#endif /* _ISOMAC */
#endif
@@ -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;
@@ -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);
}
@@ -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);
}
@@ -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))
{
@@ -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)
@@ -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:
@@ -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;
@@ -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;