* resolv/res_send.c: Add locks for res_send and res_close use.
This commit is contained in:
Ulrich Drepper 1999-07-25 00:58:33 +00:00
parent e28bacf578
commit 30f9ca19e0
2 changed files with 59 additions and 33 deletions

View File

@ -1,5 +1,7 @@
1999-07-24 Ulrich Drepper <drepper@cygnus.com> 1999-07-24 Ulrich Drepper <drepper@cygnus.com>
* resolv/res_send.c: Add locks for res_send and res_close use.
* elf/Makefile (dl-routines): Add preinit. * elf/Makefile (dl-routines): Add preinit.
* elf/Versions [ld.so] (GLIBC_2.2): Export _dl_preinit_next. * elf/Versions [ld.so] (GLIBC_2.2): Export _dl_preinit_next.
* elf/link.h (struct link_map): Add new field l_preinitcount. * elf/link.h (struct link_map): Add new field l_preinitcount.

View File

@ -87,6 +87,13 @@ static char rcsid[] = "$Id$";
# include "../conf/portability.h" # include "../conf/portability.h"
#endif #endif
#include <bits/libc-lock.h>
/* Lock to protect the connection use. */
__libc_lock_define_initialized (static, lock)
static void res_close_internal (void);
#if defined(USE_OPTIONS_H) #if defined(USE_OPTIONS_H)
# include <../conf/options.h> # include <../conf/options.h>
#endif #endif
@ -293,6 +300,7 @@ res_send(buf, buflen, ans, anssiz)
int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
register int n; register int n;
u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
int result = -1;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) { if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
/* errno should have been set by res_init() in this case. */ /* errno should have been set by res_init() in this case. */
@ -310,6 +318,8 @@ res_send(buf, buflen, ans, anssiz)
terrno = ETIMEDOUT; terrno = ETIMEDOUT;
badns = 0; badns = 0;
__libc_lock_lock (lock);
/* /*
* Send request, RETRY times, or until successful * Send request, RETRY times, or until successful
*/ */
@ -318,7 +328,7 @@ res_send(buf, buflen, ans, anssiz)
struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
same_ns: same_ns:
if (badns & (1 << ns)) { if (badns & (1 << ns)) {
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
@ -335,10 +345,11 @@ res_send(buf, buflen, ans, anssiz)
done = 1; done = 1;
break; break;
case res_nextns: case res_nextns:
res_close(); res_close_internal();
goto next_ns; goto next_ns;
case res_done: case res_done:
return (resplen); result = resplen;
goto and_out;
case res_modified: case res_modified:
/* give the hook another try */ /* give the hook another try */
if (++loops < 42) /*doug adams*/ if (++loops < 42) /*doug adams*/
@ -347,7 +358,7 @@ res_send(buf, buflen, ans, anssiz)
case res_error: case res_error:
/*FALLTHROUGH*/ /*FALLTHROUGH*/
default: default:
return (-1); goto and_out;
} }
} while (!done); } while (!done);
} }
@ -370,13 +381,13 @@ res_send(buf, buflen, ans, anssiz)
truncated = 0; truncated = 0;
if ((s < 0) || (!vc)) { if ((s < 0) || (!vc)) {
if (s >= 0) if (s >= 0)
res_close(); res_close_internal();
s = socket(PF_INET, SOCK_STREAM, 0); s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) { if (s < 0) {
terrno = errno; terrno = errno;
Perror(stderr, "socket(vc)", errno); Perror(stderr, "socket(vc)", errno);
return (-1); goto and_out;
} }
__set_errno (0); __set_errno (0);
if (connect(s, (struct sockaddr *)nsap, if (connect(s, (struct sockaddr *)nsap,
@ -385,7 +396,7 @@ res_send(buf, buflen, ans, anssiz)
Aerror(stderr, "connect/vc", Aerror(stderr, "connect/vc",
errno, *nsap); errno, *nsap);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
vc = 1; vc = 1;
@ -402,7 +413,7 @@ res_send(buf, buflen, ans, anssiz)
terrno = errno; terrno = errno;
Perror(stderr, "write failed", errno); Perror(stderr, "write failed", errno);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
/* /*
@ -419,7 +430,7 @@ read_len:
if (n <= 0) { if (n <= 0) {
terrno = errno; terrno = errno;
Perror(stderr, "read failed", errno); Perror(stderr, "read failed", errno);
res_close(); res_close_internal();
/* /*
* A long running process might get its TCP * A long running process might get its TCP
* connection reset if the remote server was * connection reset if the remote server was
@ -431,10 +442,10 @@ read_len:
*/ */
if (terrno == ECONNRESET && !connreset) { if (terrno == ECONNRESET && !connreset) {
connreset = 1; connreset = 1;
res_close(); res_close_internal();
goto same_ns; goto same_ns;
} }
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
resplen = _getshort(ans); resplen = _getshort(ans);
@ -454,7 +465,7 @@ read_len:
(stdout, ";; undersized: %d\n", len)); (stdout, ";; undersized: %d\n", len));
terrno = EMSGSIZE; terrno = EMSGSIZE;
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
cp = ans; cp = ans;
@ -466,7 +477,7 @@ read_len:
if (n <= 0) { if (n <= 0) {
terrno = errno; terrno = errno;
Perror(stderr, "read(vc)", errno); Perror(stderr, "read(vc)", errno);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
if (truncated) { if (truncated) {
@ -513,7 +524,7 @@ read_len:
if ((s < 0) || vc) { if ((s < 0) || vc) {
if (vc) if (vc)
res_close(); res_close_internal();
s = socket(PF_INET, SOCK_DGRAM, 0); s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) { if (s < 0) {
#if !CAN_RECONNECT #if !CAN_RECONNECT
@ -521,7 +532,7 @@ read_len:
#endif #endif
terrno = errno; terrno = errno;
Perror(stderr, "socket(dg)", errno); Perror(stderr, "socket(dg)", errno);
return (-1); goto and_out;
} }
connected = 0; connected = 0;
} }
@ -553,7 +564,7 @@ read_len:
"connect(dg)", "connect(dg)",
errno, *nsap); errno, *nsap);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
connected = 1; connected = 1;
@ -561,7 +572,7 @@ read_len:
if (send(s, (char*)buf, buflen, 0) != buflen) { if (send(s, (char*)buf, buflen, 0) != buflen) {
Perror(stderr, "send", errno); Perror(stderr, "send", errno);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
} else { } else {
@ -598,7 +609,7 @@ read_len:
!= buflen) { != buflen) {
Aerror(stderr, "sendto", errno, *nsap); Aerror(stderr, "sendto", errno, *nsap);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
} }
@ -614,7 +625,7 @@ read_len:
wait: wait:
if (s < 0 || s >= FD_SETSIZE) { if (s < 0 || s >= FD_SETSIZE) {
Perror(stderr, "s out-of-bounds", EMFILE); Perror(stderr, "s out-of-bounds", EMFILE);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
pfd[0].fd = s; pfd[0].fd = s;
@ -624,7 +635,7 @@ read_len:
if (errno == EINTR) if (errno == EINTR)
goto wait; goto wait;
Perror(stderr, "poll", errno); Perror(stderr, "poll", errno);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
if (n == 0) { if (n == 0) {
@ -634,7 +645,7 @@ read_len:
Dprint(_res.options & RES_DEBUG, Dprint(_res.options & RES_DEBUG,
(stdout, ";; timeout\n")); (stdout, ";; timeout\n"));
gotsomewhere = 1; gotsomewhere = 1;
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
__set_errno (0); __set_errno (0);
@ -643,7 +654,7 @@ read_len:
(struct sockaddr *)&from, &fromlen); (struct sockaddr *)&from, &fromlen);
if (resplen <= 0) { if (resplen <= 0) {
Perror(stderr, "recvfrom", errno); Perror(stderr, "recvfrom", errno);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
gotsomewhere = 1; gotsomewhere = 1;
@ -656,7 +667,7 @@ read_len:
resplen)); resplen));
terrno = EMSGSIZE; terrno = EMSGSIZE;
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
goto next_ns; goto next_ns;
} }
if (hp->id != anhp->id) { if (hp->id != anhp->id) {
@ -707,7 +718,7 @@ read_len:
(stdout, "server rejected query:\n"), (stdout, "server rejected query:\n"),
ans, (resplen>anssiz)?anssiz:resplen); ans, (resplen>anssiz)?anssiz:resplen);
badns |= (1 << ns); badns |= (1 << ns);
res_close(); res_close_internal();
/* don't retry if called from dig */ /* don't retry if called from dig */
if (!_res.pfcode) if (!_res.pfcode)
goto next_ns; goto next_ns;
@ -720,7 +731,7 @@ read_len:
Dprint(_res.options & RES_DEBUG, Dprint(_res.options & RES_DEBUG,
(stdout, ";; truncated answer\n")); (stdout, ";; truncated answer\n"));
v_circuit = 1; v_circuit = 1;
res_close(); res_close_internal();
goto same_ns; goto same_ns;
} }
} /*if vc/dg*/ } /*if vc/dg*/
@ -742,7 +753,7 @@ read_len:
*/ */
if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
!(_res.options & RES_STAYOPEN)) { !(_res.options & RES_STAYOPEN)) {
res_close(); res_close_internal();
} }
if (Rhook) { if (Rhook) {
int done = 0, loops = 0; int done = 0, loops = 0;
@ -758,7 +769,7 @@ read_len:
done = 1; done = 1;
break; break;
case res_nextns: case res_nextns:
res_close(); res_close_internal();
goto next_ns; goto next_ns;
case res_modified: case res_modified:
/* give the hook another try */ /* give the hook another try */
@ -768,16 +779,17 @@ read_len:
case res_error: case res_error:
/*FALLTHROUGH*/ /*FALLTHROUGH*/
default: default:
return (-1); goto and_out;
} }
} while (!done); } while (!done);
} }
return (resplen); result = resplen;
goto and_out;
next_ns: ; next_ns: ;
} /*foreach ns*/ } /*foreach ns*/
} /*foreach retry*/ } /*foreach retry*/
res_close(); res_close_internal();
if (!v_circuit) { if (!v_circuit) {
if (!gotsomewhere) if (!gotsomewhere)
__set_errno (ECONNREFUSED); /* no nameservers found */ __set_errno (ECONNREFUSED); /* no nameservers found */
@ -785,7 +797,11 @@ read_len:
__set_errno (ETIMEDOUT); /* no answer obtained */ __set_errno (ETIMEDOUT); /* no answer obtained */
} else } else
__set_errno (terrno); __set_errno (terrno);
return (-1);
and_out:
__libc_lock_unlock (lock);
return result;
} }
/* /*
@ -795,8 +811,8 @@ read_len:
* *
* This routine is not expected to be user visible. * This routine is not expected to be user visible.
*/ */
void static void
res_close() res_close_internal()
{ {
if (s >= 0) { if (s >= 0) {
(void) close(s); (void) close(s);
@ -806,6 +822,14 @@ res_close()
} }
} }
void
res_close ()
{
__libc_lock_lock (lock);
res_close_internal ();
__libc_lock_unlock (lock);
}
#ifdef ultrix #ifdef ultrix
/* ultrix 4.0 had some icky packaging in its libc.a. alias for it here. /* ultrix 4.0 had some icky packaging in its libc.a. alias for it here.
* there is more gunk of this kind over in res_debug.c. * there is more gunk of this kind over in res_debug.c.