about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-10-17 16:05:34 +0000
committerUlrich Drepper <drepper@redhat.com>2007-10-17 16:05:34 +0000
commitfc4837e5d7548b94630054f517eeb13f2cfaf7a9 (patch)
tree7956a7dc542c86dabdd65a707d964958d460737f /sysdeps
parent406f28dbe5f8fc70fed76a2fe0112983417ebf60 (diff)
downloadglibc-fc4837e5d7548b94630054f517eeb13f2cfaf7a9.tar.gz
glibc-fc4837e5d7548b94630054f517eeb13f2cfaf7a9.tar.xz
glibc-fc4837e5d7548b94630054f517eeb13f2cfaf7a9.zip
* sysdeps/posix/getaddrinfo.c (getaddrinfo): When sorting addresses
	and admin selects to be able to replace the gai.conf file, lock
	data structures around the qsort call.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/posix/getaddrinfo.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 8f37ec5c11..8cf9c6bdfe 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -1426,10 +1426,13 @@ in6aicmp (const void *p1, const void *p2)
 #define GAICONF_FNAME "/etc/gai.conf"
 
 
-/* Nozero if we are supposed to reload the config file automatically
+/* Non-zero if we are supposed to reload the config file automatically
    whenever it changed.  */
 static int gaiconf_reload_flag;
 
+/* Non-zero if gaiconf_reload_flag was ever set to true.  */
+static int gaiconf_reload_flag_ever_set;
+
 /* Last modification time.  */
 static struct timespec gaiconf_mtime;
 
@@ -1611,7 +1614,11 @@ gaiconf_init (void)
 
 	    case 6:
 	      if (strcmp (cmd, "reload") == 0)
-		gaiconf_reload_flag = strcmp (val1, "yes") == 0;
+		{
+		  gaiconf_reload_flag = strcmp (val1, "yes") == 0;
+		  if (gaiconf_reload_flag)
+		    gaiconf_reload_flag_ever_set = 1;
+		}
 	      break;
 
 	    case 10:
@@ -1934,9 +1941,6 @@ getaddrinfo (const char *name, const char *service,
       __libc_once_define (static, once);
       __typeof (once) old_once = once;
       __libc_once (once, gaiconf_init);
-      if (old_once && gaiconf_reload_flag)
-	gaiconf_reload ();
-
       /* Sort results according to RFC 3484.  */
       struct sort_result results[nresults];
       struct addrinfo *q;
@@ -2055,7 +2059,18 @@ getaddrinfo (const char *name, const char *service,
 
       /* We got all the source addresses we can get, now sort using
 	 the information.  */
-      qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
+      if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
+	{
+	  __libc_lock_define_initialized (static, lock);
+
+	  __libc_lock_lock (lock);
+	  if (old_once && gaiconf_reload_flag)
+	    gaiconf_reload ();
+	  qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
+	  __libc_lock_unlock (lock);
+	}
+      else
+	qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
 
       /* Queue the results up as they come out of sorting.  */
       q = p = results[0].dest_addr;