summaryrefslogtreecommitdiffstats
path: root/lib/libc/net
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-09-12 11:37:20 +0000
committerps <ps@FreeBSD.org>2000-09-12 11:37:20 +0000
commit43658697fc12aaf2d206db5e0eb78b487590c260 (patch)
tree8e2f45aafed821d528b910d4823fa503cd00538a /lib/libc/net
parent5f7726f4e7a3400d200c0152122d30f3dd541166 (diff)
downloadFreeBSD-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/libc/net')
-rw-r--r--lib/libc/net/res_send.c62
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 */
OpenPOWER on IntegriCloud