Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
	* resolv/res_send.c (send_dg): Use nonblocking sockets.  Add
	appropriate poll/select calls and restart operation if necessary.
	Also handle EINTR.
  • Loading branch information
Ulrich Drepper committed Oct 11, 2004
1 parent 7234946 commit f433b06
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 23 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
106 changes: 83 additions & 23 deletions resolv/res_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -984,53 +1046,47 @@ 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);
return (0);
}
#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
Expand All @@ -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);
Expand Down

0 comments on commit f433b06

Please sign in to comment.