diff options
author | ps <ps@FreeBSD.org> | 2000-09-12 11:37:20 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2000-09-12 11:37:20 +0000 |
commit | 43658697fc12aaf2d206db5e0eb78b487590c260 (patch) | |
tree | 8e2f45aafed821d528b910d4823fa503cd00538a /lib | |
parent | 5f7726f4e7a3400d200c0152122d30f3dd541166 (diff) | |
download | FreeBSD-src-43658697fc12aaf2d206db5e0eb78b487590c260.zip FreeBSD-src-43658697fc12aaf2d206db5e0eb78b487590c260.tar.gz |
Change from using poll(2) to kqueue/kevent when waiting for a DNS
response to return. This will stop processes waiting on DNS requests
from being woken up when a select collision occurs. This was tested
on mx1.FreeBSD.org (outgoing mail for the FreeBSD.org mailing
lists.)
Reviewed by: jlemon, peter
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/res_send.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index 5eb42cf..e720fc7 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -79,6 +79,7 @@ static char rcsid[] = "$FreeBSD$"; */ #include <sys/types.h> +#include <sys/event.h> #include <sys/param.h> #include <sys/time.h> #include <sys/socket.h> @@ -95,7 +96,6 @@ static char rcsid[] = "$FreeBSD$"; #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <poll.h> #include "res_config.h" @@ -356,6 +356,7 @@ res_send(buf, buflen, ans, anssiz) HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) ans; int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n; + int kq; u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */ if ((_res.options & RES_INIT) == 0 && res_init() == -1) { @@ -374,6 +375,11 @@ res_send(buf, buflen, ans, anssiz) terrno = ETIMEDOUT; badns = 0; + if ((kq = kqueue()) < 0) { + Perror(stderr, "kqueue", errno); + return (-1); + } + /* * Send request, RETRY times, or until successful */ @@ -414,6 +420,7 @@ res_send(buf, buflen, ans, anssiz) res_close(); goto next_ns; case res_done: + close(kq); return (resplen); case res_modified: /* give the hook another try */ @@ -423,6 +430,7 @@ res_send(buf, buflen, ans, anssiz) case res_error: /*FALLTHROUGH*/ default: + close(kq); return (-1); } } while (!done); @@ -587,9 +595,8 @@ read_len: /* * Use datagrams. */ - struct pollfd pfd; - int msec; - struct timeval timeout, itv; + struct kevent kv; + struct timespec timeout; struct sockaddr_storage from; int fromlen; @@ -693,42 +700,30 @@ read_len: * Wait for reply */ - msec = (_res.retrans << try) * 1000; + timeout.tv_sec = (_res.retrans << try); 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); - + timeout.tv_sec /= _res.nscount; + if ((long) timeout.tv_sec <= 0) + timeout.tv_sec = 1; + timeout.tv_nsec = 0; wait: if (s < 0) { Perror(stderr, "s out-of-bounds", EMFILE); res_close(); goto next_ns; } - pfd.fd = s; - pfd.events = POLLIN; - n = poll(&pfd, 1, msec); + + kv.ident = s; + kv.flags = EV_ADD | EV_ONESHOT; + kv.filter = EVFILT_READ; + + n = kevent(kq, &kv, 1, &kv, 1, &timeout); if (n < 0) { - 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; - } + if (errno == EINTR) + goto wait; + Perror(stderr, "kevent", errno); + res_close(); + goto next_ns; } if (n == 0) { @@ -873,16 +868,19 @@ read_len: case res_error: /*FALLTHROUGH*/ default: + close(kq); return (-1); } } while (!done); } + close(kq); return (resplen); next_ns: ; } /*foreach ns*/ } /*foreach retry*/ res_close(); + close(kq); if (!v_circuit) { if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ |