From ca0b9f922d3d4425fd94d697525afe06424026c0 Mon Sep 17 00:00:00 2001 From: "wtc%netscape.com" Date: Thu, 25 May 2000 02:07:07 +0000 Subject: [PATCH] Bugzilla bug #26506: removed the dns lock if the platform has gethostbyXXX_r or if the gethostbyXXX functions return the result in thread specific storage. Did this for AIX, HP-UX, IRIX, OSF1, Linux, and Solaris. Modified files: AIX.mk, HP-UX.mk, IRIX.mk, OSF1.mk, _linux.h, _solaris.h, and prnetdb.c --- nsprpub/config/AIX.mk | 8 ++ nsprpub/config/HP-UX.mk | 2 +- nsprpub/config/IRIX.mk | 3 + nsprpub/config/OSF1.mk | 3 + nsprpub/pr/include/md/_linux.h | 4 + nsprpub/pr/include/md/_solaris.h | 4 + nsprpub/pr/src/misc/prnetdb.c | 154 ++++++++++++++++++++++++++++--- 7 files changed, 162 insertions(+), 16 deletions(-) diff --git a/nsprpub/config/AIX.mk b/nsprpub/config/AIX.mk index bd40a9be25d7..9c8741bdcec9 100644 --- a/nsprpub/config/AIX.mk +++ b/nsprpub/config/AIX.mk @@ -126,6 +126,14 @@ OS_CFLAGS += -DHAVE_POINTER_LOCALTIME_R endif endif +ifeq (,$(filter-out 4.3,$(OS_RELEASE))) +# On these OS revisions, gethostbyXXX() returns result in thread +# specific storage. +ifeq ($(USE_PTHREADS),1) +OS_CFLAGS += -D_PR_HAVE_THREADSAFE_GETHOST +endif +endif + # # Special link info for constructing AIX programs. On AIX we have to # statically link programs that use NSPR into a single .o, rewriting the diff --git a/nsprpub/config/HP-UX.mk b/nsprpub/config/HP-UX.mk index 371de60b8d0a..aebfbebe6648 100644 --- a/nsprpub/config/HP-UX.mk +++ b/nsprpub/config/HP-UX.mk @@ -166,7 +166,7 @@ ifdef USE_PTHREADS ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE))) OS_CFLAGS += -D_REENTRANT -D_PR_DCETHREADS else -OS_CFLAGS += -D_POSIX_C_SOURCE=199506L +OS_CFLAGS += -D_POSIX_C_SOURCE=199506L -D_PR_HAVE_THREADSAFE_GETHOST endif endif diff --git a/nsprpub/config/IRIX.mk b/nsprpub/config/IRIX.mk index 44b86fd1d788..caac61efe16f 100644 --- a/nsprpub/config/IRIX.mk +++ b/nsprpub/config/IRIX.mk @@ -123,6 +123,9 @@ ifndef NS_USE_GCC OS_CFLAGS += -mips3 endif OS_CFLAGS += -D_PR_HAVE_GETPROTO_R -D_PR_HAVE_GETPROTO_R_POINTER +ifeq ($(USE_PTHREADS),1) +OS_CFLAGS += -D_PR_HAVE_GETHOST_R -D_PR_HAVE_GETHOST_R_POINTER +endif endif ifndef NO_MDUPDATE diff --git a/nsprpub/config/OSF1.mk b/nsprpub/config/OSF1.mk index dcf9b16cefc0..6fc5b2e80dc1 100644 --- a/nsprpub/config/OSF1.mk +++ b/nsprpub/config/OSF1.mk @@ -92,6 +92,9 @@ endif ifeq ($(USE_PTHREADS),1) OS_CFLAGS += -pthread +ifneq (,$(filter-out V2.0 V3.2,$(OS_RELEASE))) +OS_CFLAGS += -D_PR_HAVE_THREADSAFE_GETHOST +endif endif # The command to build a shared library on OSF1. diff --git a/nsprpub/pr/include/md/_linux.h b/nsprpub/pr/include/md/_linux.h index 96905cf202e2..ca0dea16694f 100644 --- a/nsprpub/pr/include/md/_linux.h +++ b/nsprpub/pr/include/md/_linux.h @@ -90,6 +90,10 @@ extern PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval); #endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#if (__GLIBC__ >= 2) && defined(_PR_PTHREADS) +#define _PR_HAVE_GETHOST_R +#define _PR_HAVE_GETHOST_R_INT +#endif #ifdef _PR_PTHREADS diff --git a/nsprpub/pr/include/md/_solaris.h b/nsprpub/pr/include/md/_solaris.h index 5a16750ce363..5f8ee3342551 100644 --- a/nsprpub/pr/include/md/_solaris.h +++ b/nsprpub/pr/include/md/_solaris.h @@ -87,6 +87,10 @@ #define AI_ALL 0x0002 #define AI_ADDRCONFIG 0x0004 #endif +#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS) +#define _PR_HAVE_GETHOST_R +#define _PR_HAVE_GETHOST_R_POINTER +#endif #include "prinrval.h" NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void); diff --git a/nsprpub/pr/src/misc/prnetdb.c b/nsprpub/pr/src/misc/prnetdb.c index 6a8293a4d624..3b709d41f014 100644 --- a/nsprpub/pr/src/misc/prnetdb.c +++ b/nsprpub/pr/src/misc/prnetdb.c @@ -34,14 +34,32 @@ extern int h_errno; #define _MD_GETHOST_ERRNO() _MD_ERRNO() #endif -#if defined(_PR_NO_PREEMPT) +/* + * The meaning of the macros related to gethostbyname, gethostbyaddr, + * and gethostbyname2 is defined below. + * - _PR_HAVE_THREADSAFE_GETHOST: the gethostbyXXX functions return + * the result in thread specific storage. For example, AIX, HP-UX, + * and OSF1. + * - _PR_HAVE_GETHOST_R: have the gethostbyXXX_r functions. See next + * two macros. + * - _PR_HAVE_GETHOST_R_INT: the gethostbyXXX_r functions return an + * int. For example, Linux glibc. + * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return + * a struct hostent* pointer. For example, Solaris and IRIX. + */ +#if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \ + || defined(_PR_HAVE_THREADSAFE_GETHOST) +#define _PR_NO_DNS_LOCK +#endif + +#if defined(_PR_NO_DNS_LOCK) #define LOCK_DNS() #define UNLOCK_DNS() #else PRLock *_pr_dnsLock = NULL; #define LOCK_DNS() PR_Lock(_pr_dnsLock) #define UNLOCK_DNS() PR_Unlock(_pr_dnsLock) -#endif /* defined(_PR_NO_PREEMPT) */ +#endif /* defined(_PR_NO_DNS_LOCK) */ /* * Some platforms have the reentrant getprotobyname_r() and @@ -134,7 +152,7 @@ void _PR_InitNet(void) (void)setnetconfig(); #endif #endif -#if !defined(_PR_NO_PREEMPT) +#if !defined(_PR_NO_DNS_LOCK) _pr_dnsLock = PR_NewLock(); #endif #if !defined(_PR_HAVE_GETPROTO_R) @@ -319,20 +337,74 @@ static PRStatus CopyProtoent( } #endif /* !defined(_PR_HAVE_GETPROTO_R) */ +/* + * ################################################################# + * NOTE: tmphe, tmpbuf, bufsize, h, and h_err are local variables + * or arguments of PR_GetHostByName, PR_GetIPNodeByName, and + * PR_GetHostByAddr. DO NOT CHANGE THE NAMES OF THESE LOCAL + * VARIABLES OR ARGUMENTS. + * ################################################################# + */ +#if defined(_PR_HAVE_GETHOST_R_INT) + +#define GETHOSTBYNAME(name) \ + (gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &h_err), h) +#define GETHOSTBYNAME2(name, af) \ + (gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h) +#define GETHOSTBYADDR(addr, addrlen, af) \ + (gethostbyaddr_r(addr, addrlen, af, \ + &tmphe, tmpbuf, bufsize, &h, &h_err), h) + +#elif defined(_PR_HAVE_GETHOST_R_POINTER) + +#define GETHOSTBYNAME(name) \ + gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h_err) +#define GETHOSTBYNAME2(name, af) \ + gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h_err) +#define GETHOSTBYADDR(addr, addrlen, af) \ + gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize, &h_err) + +#else + +#define GETHOSTBYNAME(name) gethostbyname(name) +#define GETHOSTBYNAME2(name, af) gethostbyname2(name, af) +#define GETHOSTBYADDR(addr, addrlen, af) gethostbyaddr(addr, addrlen, af) + +#endif /* definition of GETHOSTBYXXX */ + PR_IMPLEMENT(PRStatus) PR_GetHostByName( const char *name, char *buf, PRIntn bufsize, PRHostEnt *hp) { struct hostent *h; PRStatus rv = PR_FAILURE; +#if defined(_PR_HAVE_GETHOST_R) + char localbuf[PR_NETDB_BUF_SIZE]; + char *tmpbuf; + struct hostent tmphe; + int h_err; +#endif if (!_pr_initialized) _PR_ImplicitInitialization(); +#if defined(_PR_HAVE_GETHOST_R) + tmpbuf = localbuf; + if (bufsize > sizeof(localbuf)) + { + tmpbuf = PR_Malloc(bufsize); + if (NULL == tmpbuf) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return rv; + } + } +#endif + LOCK_DNS(); #ifdef XP_OS2_VACPP - h = gethostbyname((char *)name); + h = GETHOSTBYNAME((char *)name); #else - h = gethostbyname(name); + h = GETHOSTBYNAME(name); #endif if (NULL == h) @@ -347,6 +419,10 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } UNLOCK_DNS(); +#if defined(_PR_HAVE_GETHOST_R) + if (tmpbuf != localbuf) + PR_Free(tmpbuf); +#endif return rv; } @@ -407,6 +483,12 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( { struct hostent *h = 0; PRStatus rv = PR_FAILURE; +#if defined(_PR_HAVE_GETHOST_R) + char localbuf[PR_NETDB_BUF_SIZE]; + char *tmpbuf; + struct hostent tmphe; + int h_err; +#endif #if defined(_PR_HAVE_GETIPNODEBYNAME) PRUint16 md_af = af; int error_num; @@ -437,6 +519,19 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( md_af = af; #endif +#if defined(_PR_HAVE_GETHOST_R) + tmpbuf = localbuf; + if (bufsize > sizeof(localbuf)) + { + tmpbuf = PR_Malloc(bufsize); + if (NULL == tmpbuf) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return rv; + } + } +#endif + /* Do not need to lock the DNS lock if getipnodebyname() is called */ #ifdef _PR_INET6 #ifdef _PR_HAVE_GETHOSTBYNAME2 @@ -446,17 +541,17 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( #ifdef _PR_INET6_PROBE if (_pr_ipv6_is_present == PR_TRUE) #endif - h = gethostbyname2(name, AF_INET6); + h = GETHOSTBYNAME2(name, AF_INET6); if ((NULL == h) && (flags & PR_AI_V4MAPPED)) { did_af_inet = PR_TRUE; - h = gethostbyname2(name, AF_INET); + h = GETHOSTBYNAME2(name, AF_INET); } } else { did_af_inet = PR_TRUE; - h = gethostbyname2(name, af); + h = GETHOSTBYNAME2(name, af); } #elif defined(_PR_HAVE_GETIPNODEBYNAME) h = getipnodebyname(name, md_af, tmp_flags, &error_num); @@ -469,14 +564,14 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( else { LOCK_DNS(); - h = gethostbyname(name); + h = GETHOSTBYNAME(name); } #else /* _PR_INET6 */ LOCK_DNS(); #ifdef XP_OS2_VACPP - h = gethostbyname((char *)name); + h = GETHOSTBYNAME((char *)name); #else - h = gethostbyname(name); + h = GETHOSTBYNAME(name); #endif #endif /* _PR_INET6 */ @@ -510,7 +605,7 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED) && (flags & (PR_AI_ALL|PR_AI_ADDRCONFIG)) - && !did_af_inet && (h = gethostbyname2(name, AF_INET)) != 0) { + && !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)) != 0) { rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); @@ -530,6 +625,11 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( UNLOCK_DNS(); #endif /* _PR_INET6 */ +#if defined(_PR_HAVE_GETHOST_R) + if (tmpbuf != localbuf) + PR_Free(tmpbuf); +#endif + return rv; } @@ -542,6 +642,12 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( PRUint32 tmp_ip; int addrlen; PRInt32 af; +#if defined(_PR_HAVE_GETHOST_R) + char localbuf[PR_NETDB_BUF_SIZE]; + char *tmpbuf; + struct hostent tmphe; + int h_err; +#endif #if defined(_PR_HAVE_GETIPNODEBYADDR) int error_num; #endif @@ -592,6 +698,19 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( addrlen = sizeof(hostaddr->inet.ip); } +#if defined(_PR_HAVE_GETHOST_R) + tmpbuf = localbuf; + if (bufsize > sizeof(localbuf)) + { + tmpbuf = PR_Malloc(bufsize); + if (NULL == tmpbuf) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return rv; + } + } +#endif + /* Do not need to lock the DNS lock if getipnodebyaddr() is called */ #if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6) h = getipnodebyaddr(addr, addrlen, af, &error_num); @@ -602,14 +721,14 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( else { LOCK_DNS(); - h = gethostbyaddr(addr, addrlen, af); + h = GETHOSTBYADDR(addr, addrlen, af); } #else /* _PR_HAVE_GETIPNODEBYADDR */ LOCK_DNS(); #ifdef XP_OS2_VACPP - h = gethostbyaddr((char *)addr, addrlen, af); + h = GETHOSTBYADDR((char *)addr, addrlen, af); #else - h = gethostbyaddr(addr, addrlen, af); + h = GETHOSTBYADDR(addr, addrlen, af); #endif #endif /* _PR_HAVE_GETIPNODEBYADDR */ if (NULL == h) @@ -660,6 +779,11 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( UNLOCK_DNS(); #endif /* _PR_HAVE_GETIPNODEBYADDR */ +#if defined(_PR_HAVE_GETHOST_R) + if (tmpbuf != localbuf) + PR_Free(tmpbuf); +#endif + return rv; }