From 43658697fc12aaf2d206db5e0eb78b487590c260 Mon Sep 17 00:00:00 2001 From: ps Date: Tue, 12 Sep 2000 11:37:20 +0000 Subject: 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 --- lib/libc/net/res_send.c | 62 ++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'lib/libc/net') 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 +#include #include #include #include @@ -95,7 +96,6 @@ static char rcsid[] = "$FreeBSD$"; #include #include #include -#include #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 */ -- cgit v1.1