mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-24 02:03:35 +08:00
Update.
* resolv/res_send.c (send_dg): Use nonblocking sockets. Add appropriate poll/select calls and restart operation if necessary. Also handle EINTR.
This commit is contained in:
parent
7234946661
commit
f433b06b83
@ -1,5 +1,9 @@
|
||||
2004-10-11 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* resolv/res_send.c (send_dg): Use nonblocking sockets. Add
|
||||
appropriate poll/select calls and restart operation if necessary.
|
||||
Also handle EINTR.
|
||||
|
||||
* elf/tst-dlopenrpath.c (do_test): Enable code which was disabled
|
||||
for debugging.
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user