summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2000-03-26 19:20:50 +0000
committerjlemon <jlemon@FreeBSD.org>2000-03-26 19:20:50 +0000
commit8ab55710ca57591b2f1a2d1cb8e149a8a6496d99 (patch)
tree9eae61a408644aa3167d46d57a4245e85330dd60 /lib
parentd94da0bbbc2b89c1dca78f4ff01e91fb3db59fc9 (diff)
downloadFreeBSD-src-8ab55710ca57591b2f1a2d1cb8e149a8a6496d99.zip
FreeBSD-src-8ab55710ca57591b2f1a2d1cb8e149a8a6496d99.tar.gz
Decrement the timeout being passed to poll() if poll was interrupted for
some reason. This will prevent an infinite loop if (say) a sigalarm is being scheduled at a more frequent interval than the poll timeout. PR: 2191, 8847, 10553
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/net/res_send.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c
index 68a7c60..895db81 100644
--- a/lib/libc/net/res_send.c
+++ b/lib/libc/net/res_send.c
@@ -635,11 +635,17 @@ read_len:
#ifndef NOPOLL
othersyscall:
if (use_poll) {
+ struct timeval itv;
+
msec = (_res.retrans << try) * 1000;
if (try > 0)
msec /= _res.nscount;
if (msec <= 0)
msec = 1000;
+ gettimeofday(&timeout, NULL);
+ itv.tv_sec = msec / 1000;
+ itv.tv_usec = (msec % 1000) * 1000;
+ timeradd(&timeout, &itv, &timeout);
} else {
#endif
timeout.tv_sec = (_res.retrans << try);
@@ -685,11 +691,22 @@ read_len:
} else if (use_poll == 1)
use_poll = 2;
if (n < 0) {
- if (errno == EINTR)
- goto wait;
- Perror(stderr, "poll", errno);
- res_close();
- goto next_ns;
+ if (errno == EINTR) {
+ struct timeval ctv;
+
+ gettimeofday(&ctv, NULL);
+ if (timercmp(&ctv, &timeout, <)) {
+ timersub(&timeout,
+ &ctv, &ctv);
+ msec = ctv.tv_sec * 1000;
+ msec += ctv.tv_usec / 1000;
+ goto wait;
+ }
+ } else {
+ Perror(stderr, "poll", errno);
+ res_close();
+ goto next_ns;
+ }
}
} else {
#endif
OpenPOWER on IntegriCloud