diff options
author | jlemon <jlemon@FreeBSD.org> | 2000-03-26 19:20:50 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2000-03-26 19:20:50 +0000 |
commit | 8ab55710ca57591b2f1a2d1cb8e149a8a6496d99 (patch) | |
tree | 9eae61a408644aa3167d46d57a4245e85330dd60 /lib/libc | |
parent | d94da0bbbc2b89c1dca78f4ff01e91fb3db59fc9 (diff) | |
download | FreeBSD-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/libc')
-rw-r--r-- | lib/libc/net/res_send.c | 27 |
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 |