diff options
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/res_init.c | 3 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 2 | ||||
-rw-r--r-- | resolv/res_send.c | 106 |
3 files changed, 87 insertions, 24 deletions
diff --git a/resolv/res_init.c b/resolv/res_init.c index 4087597a87..731c784e17 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -597,6 +597,9 @@ res_thread_freeres (void) free (_res._u._ext.nsaddrs[ns]); _res._u._ext.nsaddrs[ns] = NULL; } + + /* Make sure we do a full re-initialization the next time. */ + _res.options = 0; } text_set_element (__libc_thread_subfreeres, res_thread_freeres); text_set_element (__libc_subfreeres, res_thread_freeres); diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 5b705b0e8b..9825ae0fa3 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -141,7 +141,7 @@ res_nmkquery(res_state statp, randombits = (tv.tv_sec << 8) ^ tv.tv_usec; #endif } - while (randombits == 0); + while ((randombits & 0xffff) == 0); statp->id = (statp->id + randombits) & 0xffff; #endif hp->opcode = op; diff --git a/resolv/res_send.c b/resolv/res_send.c index 2366f59cd2..44d8cb0fee 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -88,6 +88,7 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi #include <sys/ioctl.h> #include <errno.h> +#include <fcntl.h> #include <netdb.h> #include <resolv.h> #include <signal.h> @@ -965,12 +966,73 @@ send_dg(res_state statp, return (0); } #endif /* !CANNOT_CONNECT_DGRAM */ + /* Make socket non-blocking. */ + int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL); + if (fl != -1) + __fcntl (EXT(statp).nssocks[ns], F_SETFL, + fl | O_NONBLOCK); Dprint(statp->options & RES_DEBUG, (stdout, ";; new DG socket\n")) } s = EXT(statp).nssocks[ns]; + /* + * Compute time for the total operation. + */ + seconds = (statp->retrans << ns); + if (ns > 0) + seconds /= statp->nscount; + if (seconds <= 0) + seconds = 1; + evNowTime(&now); + evConsTime(&timeout, seconds, 0); + evAddTime(&finish, &now, &timeout); + int need_recompute = 0; + resend: +#ifdef _LIBC + /* Convert struct timespec in milliseconds. */ + ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000; + + pfd[0].fd = s; + pfd[0].events = POLLOUT; + n = __poll (pfd, 1, 0); + if (__builtin_expect (n == 0, 0)) { + n = __poll (pfd, 1, ptimeout); + need_recompute = 1; + } +#else + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + struct timeval zerotime = { 0, 0 }; + n = pselect(s + 1, NULL, &dsmask, NULL, &zerotime, NULL); + if (n == 0) { + n = pselect(s + 1, NULL, &dsmask, NULL, &timeout, NULL); + need_recompute = 1; + } +#endif + if (n == 0) { + Dprint(statp->options & RES_DEBUG, (stdout, + ";; timeout sending\n")); + *gotsomewhere = 1; + return (0); + } + if (n < 0) { + if (errno == EINTR) { + recompute_resend: + evNowTime(&now); + if (evCmpTime(finish, now) > 0) { + evSubTime(&timeout, &finish, &now); + goto resend; + } + } + Perror(statp, stderr, "select", errno); + res_nclose(statp); + return (0); + } + __set_errno (0); #ifndef CANNOT_CONNECT_DGRAM if (send(s, (char*)buf, buflen, 0) != buflen) { + if (errno == EINTR || errno == EAGAIN) + goto recompute_resend; Perror(statp, stderr, "send", errno); res_nclose(statp); return (0); @@ -984,6 +1046,8 @@ send_dg(res_state statp, if (sendto(s, (char*)buf, buflen, 0, (struct sockaddr *)nsap, sizeof *nsap) != buflen) { + if (errno == EINTR || errno == EAGAIN) + goto recompute_resend; Aerror(statp, stderr, "sendto", errno, (struct sockaddr *) nsap); res_nclose(statp); @@ -991,46 +1055,38 @@ send_dg(res_state statp, } #endif /* !CANNOT_CONNECT_DGRAM */ - /* - * Wait for reply. - */ - seconds = (statp->retrans << ns); - if (ns > 0) - seconds /= statp->nscount; - if (seconds <= 0) - seconds = 1; - evNowTime(&now); - evConsTime(&timeout, seconds, 0); - evAddTime(&finish, &now, &timeout); wait: + if (need_recompute) { + evNowTime(&now); + if (evCmpTime(finish, now) <= 0) { + err_return: + Perror(statp, stderr, "select", errno); + res_nclose(statp); + return (0); + } + evSubTime(&timeout, &finish, &now); + } #ifdef _LIBC /* Convert struct timespec in milliseconds. */ ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000; - pfd[0].fd = s; pfd[0].events = POLLIN; n = __poll (pfd, 1, ptimeout); #else - FD_ZERO(&dsmask); - FD_SET(s, &dsmask); n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); #endif if (n == 0) { - Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); + Dprint(statp->options & RES_DEBUG, (stdout, + ";; timeout receiving\n")); *gotsomewhere = 1; return (0); } if (n < 0) { if (errno == EINTR) { - evNowTime(&now); - if (evCmpTime(finish, now) > 0) { - evSubTime(&timeout, &finish, &now); - goto wait; - } + need_recompute = 1; + goto wait; } - Perror(statp, stderr, "select", errno); - res_nclose(statp); - return (0); + goto err_return; } __set_errno (0); #ifdef _LIBC @@ -1056,6 +1112,10 @@ send_dg(res_state statp, resplen = recvfrom(s, (char*)ans, anssiz,0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { + if (errno == EINTR || errno == EAGAIN) { + need_recompute = 1; + goto wait; + } Perror(statp, stderr, "recvfrom", errno); res_nclose(statp); return (0); |