Merge "Initialize _nres only once" am: 24e0b57429 am: 5ffb5a6882

Original change: https://android-review.googlesource.com/c/platform/bionic/+/1534576

Change-Id: I17ae65cf42eddd4e9f8d22061fd0344a98c51c59
diff --git a/libc/dns/resolv/res_data.c b/libc/dns/resolv/res_data.c
index 9bc02e7..4f8df69 100644
--- a/libc/dns/resolv/res_data.c
+++ b/libc/dns/resolv/res_data.c
@@ -40,6 +40,7 @@
 #include <ctype.h>
 #include <netdb.h>
 #include "resolv_private.h"
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -82,11 +83,9 @@
 
 int  res_ourserver_p(const res_state, const struct sockaddr *);
 
-#define res_need_init()   ((_nres.options & RES_INIT) == 0U)
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
 
-int
-res_init(void) {
-	int rv;
+static void init_once(void) {
 	extern int __res_vinit(res_state, int);
 #ifdef COMPAT__RES
 	/*
@@ -140,11 +139,21 @@
 	if (!_nres.id)
 		_nres.id = res_randomid();
 
-	rv = __res_vinit(&_nres, 1);
+	__res_vinit(&_nres, 1);
 #ifdef COMPAT__RES
 	__res_put_old_state(&_nres);
 #endif
-	return rv;
+}
+
+int
+res_init(void) {
+    pthread_once(&once_control, init_once);
+    return 0;
+}
+
+static res_state get_static_res_state() {
+    pthread_once(&once_control, init_once);
+    return &_nres;
 }
 
 void
@@ -159,10 +168,7 @@
 
 void
 fp_nquery(const u_char *msg, int len, FILE *file) {
-	if (res_need_init() && res_init() == -1)
-		return;
-
-	res_pquery(&_nres, msg, len, file);
+	res_pquery(get_static_res_state(), msg, len, file);
 }
 
 int
@@ -175,11 +181,7 @@
 	    u_char *buf,		/* buffer to put query */
 	    int buflen)			/* size of buffer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-	return (res_nmkquery(&_nres, op, dname, class, type,
+	return (res_nmkquery(get_static_res_state(), op, dname, class, type,
 			     data, datalen,
 			     newrr_in, buf, buflen));
 }
@@ -187,12 +189,7 @@
 #ifdef _LIBRESOLV
 int
 res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nmkupdate(&_nres, rrecp_in, buf, buflen));
+	return (res_nmkupdate(get_static_res_state(), rrecp_in, buf, buflen));
 }
 #endif
 
@@ -202,11 +199,7 @@
 	  u_char *answer,	/* buffer to put answer */
 	  int anslen)		/* size of answer buffer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-	return (res_nquery(&_nres, name, class, type, answer, anslen));
+	return (res_nquery(get_static_res_state(), name, class, type, answer, anslen));
 }
 
 void
@@ -226,12 +219,7 @@
 
 int
 res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
-	if (res_need_init() && res_init() == -1) {
-		/* errno should have been set by res_init() in this case. */
-		return (-1);
-	}
-
-	return (res_nsend(&_nres, buf, buflen, ans, anssiz));
+	return (res_nsend(get_static_res_state(), buf, buflen, ans, anssiz));
 }
 
 #ifdef _LIBRESOLV
@@ -239,12 +227,7 @@
 res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
 	       u_char *ans, int anssiz)
 {
-	if (res_need_init() && res_init() == -1) {
-		/* errno should have been set by res_init() in this case. */
-		return (-1);
-	}
-
-	return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz));
+	return (res_nsendsigned(get_static_res_state(), buf, buflen, key, ans, anssiz));
 }
 #endif
 
@@ -256,12 +239,7 @@
 #ifdef _LIBRESOLV
 int
 res_update(ns_updrec *rrecp_in) {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nupdate(&_nres, rrecp_in, NULL));
+	return (res_nupdate(get_static_res_state(), rrecp_in, NULL));
 }
 #endif
 
@@ -271,12 +249,7 @@
 	   u_char *answer,	/* buffer to put answer */
 	   int anslen)		/* size of answer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nsearch(&_nres, name, class, type, answer, anslen));
+	return (res_nsearch(get_static_res_state(), name, class, type, answer, anslen));
 }
 
 int
@@ -286,12 +259,7 @@
 		u_char *answer,		/* buffer to put answer */
 		int anslen)		/* size of answer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nquerydomain(&_nres, name, domain,
+	return (res_nquerydomain(get_static_res_state(), name, domain,
 				 class, type,
 				 answer, anslen));
 }