Update.
authorUlrich Drepper <drepper@redhat.com>
Sun, 25 Jul 1999 00:58:33 +0000 (00:58 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sun, 25 Jul 1999 00:58:33 +0000 (00:58 +0000)
* resolv/res_send.c: Add locks for res_send and res_close use.

ChangeLog
resolv/res_send.c

index cf81692..f6d5b7a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 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/Versions [ld.so] (GLIBC_2.2): Export _dl_preinit_next.
        * elf/link.h (struct link_map): Add new field l_preinitcount.
index d976198..0c67d50 100644 (file)
@@ -87,6 +87,13 @@ static char rcsid[] = "$Id$";
 # include "../conf/portability.h"
 #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)
 # include <../conf/options.h>
 #endif
@@ -293,6 +300,7 @@ res_send(buf, buflen, ans, anssiz)
        int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
        register int n;
        u_int badns;    /* XXX NSMAX can't exceed #/bits in this var */
+       int result = -1;
 
        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
                /* errno should have been set by res_init() in this case. */
@@ -310,6 +318,8 @@ res_send(buf, buflen, ans, anssiz)
        terrno = ETIMEDOUT;
        badns = 0;
 
+       __libc_lock_lock (lock);
+
        /*
         * 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];
     same_ns:
                if (badns & (1 << ns)) {
-                       res_close();
+                       res_close_internal();
                        goto next_ns;
                }
 
@@ -335,10 +345,11 @@ res_send(buf, buflen, ans, anssiz)
                                        done = 1;
                                        break;
                                case res_nextns:
-                                       res_close();
+                                       res_close_internal();
                                        goto next_ns;
                                case res_done:
-                                       return (resplen);
+                                       result = resplen;
+                                       goto and_out;
                                case res_modified:
                                        /* give the hook another try */
                                        if (++loops < 42) /*doug adams*/
@@ -347,7 +358,7 @@ res_send(buf, buflen, ans, anssiz)
                                case res_error:
                                        /*FALLTHROUGH*/
                                default:
-                                       return (-1);
+                                       goto and_out;
                                }
                        } while (!done);
                }
@@ -370,13 +381,13 @@ res_send(buf, buflen, ans, anssiz)
                        truncated = 0;
                        if ((s < 0) || (!vc)) {
                                if (s >= 0)
-                                       res_close();
+                                       res_close_internal();
 
                                s = socket(PF_INET, SOCK_STREAM, 0);
                                if (s < 0) {
                                        terrno = errno;
                                        Perror(stderr, "socket(vc)", errno);
-                                       return (-1);
+                                       goto and_out;
                                }
                                __set_errno (0);
                                if (connect(s, (struct sockaddr *)nsap,
@@ -385,7 +396,7 @@ res_send(buf, buflen, ans, anssiz)
                                        Aerror(stderr, "connect/vc",
                                               errno, *nsap);
                                        badns |= (1 << ns);
-                                       res_close();
+                                       res_close_internal();
                                        goto next_ns;
                                }
                                vc = 1;
@@ -402,7 +413,7 @@ res_send(buf, buflen, ans, anssiz)
                                terrno = errno;
                                Perror(stderr, "write failed", errno);
                                badns |= (1 << ns);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        /*
@@ -419,7 +430,7 @@ read_len:
                        if (n <= 0) {
                                terrno = errno;
                                Perror(stderr, "read failed", errno);
-                               res_close();
+                               res_close_internal();
                                /*
                                 * A long running process might get its TCP
                                 * connection reset if the remote server was
@@ -431,10 +442,10 @@ read_len:
                                 */
                                if (terrno == ECONNRESET && !connreset) {
                                        connreset = 1;
-                                       res_close();
+                                       res_close_internal();
                                        goto same_ns;
                                }
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        resplen = _getshort(ans);
@@ -454,7 +465,7 @@ read_len:
                                       (stdout, ";; undersized: %d\n", len));
                                terrno = EMSGSIZE;
                                badns |= (1 << ns);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        cp = ans;
@@ -466,7 +477,7 @@ read_len:
                        if (n <= 0) {
                                terrno = errno;
                                Perror(stderr, "read(vc)", errno);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        if (truncated) {
@@ -513,7 +524,7 @@ read_len:
 
                        if ((s < 0) || vc) {
                                if (vc)
-                                       res_close();
+                                       res_close_internal();
                                s = socket(PF_INET, SOCK_DGRAM, 0);
                                if (s < 0) {
 #if !CAN_RECONNECT
@@ -521,7 +532,7 @@ read_len:
 #endif
                                        terrno = errno;
                                        Perror(stderr, "socket(dg)", errno);
-                                       return (-1);
+                                       goto and_out;
                                }
                                connected = 0;
                        }
@@ -553,7 +564,7 @@ read_len:
                                                       "connect(dg)",
                                                       errno, *nsap);
                                                badns |= (1 << ns);
-                                               res_close();
+                                               res_close_internal();
                                                goto next_ns;
                                        }
                                        connected = 1;
@@ -561,7 +572,7 @@ read_len:
                                if (send(s, (char*)buf, buflen, 0) != buflen) {
                                        Perror(stderr, "send", errno);
                                        badns |= (1 << ns);
-                                       res_close();
+                                       res_close_internal();
                                        goto next_ns;
                                }
                        } else {
@@ -598,7 +609,7 @@ read_len:
                                    != buflen) {
                                        Aerror(stderr, "sendto", errno, *nsap);
                                        badns |= (1 << ns);
-                                       res_close();
+                                       res_close_internal();
                                        goto next_ns;
                                }
                        }
@@ -614,7 +625,7 @@ read_len:
     wait:
                        if (s < 0 || s >= FD_SETSIZE) {
                                Perror(stderr, "s out-of-bounds", EMFILE);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        pfd[0].fd = s;
@@ -624,7 +635,7 @@ read_len:
                                if (errno == EINTR)
                                        goto wait;
                                Perror(stderr, "poll", errno);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        if (n == 0) {
@@ -634,7 +645,7 @@ read_len:
                                Dprint(_res.options & RES_DEBUG,
                                       (stdout, ";; timeout\n"));
                                gotsomewhere = 1;
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        __set_errno (0);
@@ -643,7 +654,7 @@ read_len:
                                           (struct sockaddr *)&from, &fromlen);
                        if (resplen <= 0) {
                                Perror(stderr, "recvfrom", errno);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        gotsomewhere = 1;
@@ -656,7 +667,7 @@ read_len:
                                        resplen));
                                terrno = EMSGSIZE;
                                badns |= (1 << ns);
-                               res_close();
+                               res_close_internal();
                                goto next_ns;
                        }
                        if (hp->id != anhp->id) {
@@ -707,7 +718,7 @@ read_len:
                                        (stdout, "server rejected query:\n"),
                                        ans, (resplen>anssiz)?anssiz:resplen);
                                badns |= (1 << ns);
-                               res_close();
+                               res_close_internal();
                                /* don't retry if called from dig */
                                if (!_res.pfcode)
                                        goto next_ns;
@@ -720,7 +731,7 @@ read_len:
                                Dprint(_res.options & RES_DEBUG,
                                       (stdout, ";; truncated answer\n"));
                                v_circuit = 1;
-                               res_close();
+                               res_close_internal();
                                goto same_ns;
                        }
                } /*if vc/dg*/
@@ -742,7 +753,7 @@ read_len:
                 */
                if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
                    !(_res.options & RES_STAYOPEN)) {
-                       res_close();
+                       res_close_internal();
                }
                if (Rhook) {
                        int done = 0, loops = 0;
@@ -758,7 +769,7 @@ read_len:
                                        done = 1;
                                        break;
                                case res_nextns:
-                                       res_close();
+                                       res_close_internal();
                                        goto next_ns;
                                case res_modified:
                                        /* give the hook another try */
@@ -768,16 +779,17 @@ read_len:
                                case res_error:
                                        /*FALLTHROUGH*/
                                default:
-                                       return (-1);
+                                       goto and_out;
                                }
                        } while (!done);
 
                }
-               return (resplen);
+               result = resplen;
+               goto and_out;
     next_ns: ;
           } /*foreach ns*/
        } /*foreach retry*/
-       res_close();
+       res_close_internal();
        if (!v_circuit) {
                if (!gotsomewhere)
                        __set_errno (ECONNREFUSED); /* no nameservers found */
@@ -785,7 +797,11 @@ read_len:
                        __set_errno (ETIMEDOUT);    /* no answer obtained */
        } else
                __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.
  */
-void
-res_close()
+static void
+res_close_internal()
 {
        if (s >= 0) {
                (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
 /* 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.