You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Justin Erenkrantz <je...@ebuilt.com> on 2001/07/20 08:17:17 UTC

[PATCH] #2 was Re: [PATCH] Add reentrant gethostbyname call

Improvements and notes since my original posting:

- Use autoconf detection to try to eliminate chances where we may
  not need gethostbyname_r

- Fixed one long line that bugged me.

- Bump up buffersize to 512 since it may be larger than I thought
  (need to give Roy more Dr. Pepper).  I was using it with 256 
  before and didn't see any problem, but 512 is a bit more 
  conservative.  Hopefully if the user runs out of range, whatever 
  calls this function will notice the error (ERANGE) and report 
  it to us and we can bump the #define if need be.

- AFAICT, gethostbyname_r is *not* defined in POSIX 1003.1c-1995, so 
  we can't use _POSIX_THREAD_SAFE_FUNCTIONS as we can for readdir_r.

- Solaris 8, which has getipnodebyname and getaddrinfo, also has
  IPV6, so it takes a completely different code path.  We were 
  using Solaris 7 today, so that may be why I haven't seen problems 
  before now.

- Roy mentioned that the gethostbyname_r in Solaris has different
  semantics than POSIX.  Well, I can't/don't have access to any 
  platforms that uses the different prototype.  So, if there is 
  another platform out there that has gethostbyname_r with a
  different prototype, you'll have to add in the tweaks or submit 
  patches.  Sorry.

I'll plan on committing in the morning unless I receive any
objections.  I wonder how many more of these non-threadsafe 
functions we're using with threads.  =(  -- justin

Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.339
diff -u -r1.339 configure.in
--- configure.in	2001/07/14 00:13:36	1.339
+++ configure.in	2001/07/20 05:56:47
@@ -326,9 +326,12 @@
 fi
 
 ac_cv_define_READDIR_IS_THREAD_SAFE=no
+ac_cv_define_GETHOSTBYNAME_IS_THREAD_SAFE=no
 if test "$threads" = "1"; then
     echo "APR will use threads"
     AC_CHECK_LIB(c_r, readdir, AC_DEFINE(READDIR_IS_THREAD_SAFE))
+    AC_CHECK_LIB(c_r, gethostbyname, AC_DEFINE(GETHOSTBYNAME_IS_THREAD_SAFE))
+    AC_CHECK_FUNCS(gethostbyname_r)
 else
     echo "APR will be non-threaded"
 fi
Index: acconfig.h
===================================================================
RCS file: /home/cvs/apr/acconfig.h,v
retrieving revision 1.46
diff -u -r1.46 acconfig.h
--- acconfig.h	2001/07/02 18:54:05	1.46
+++ acconfig.h	2001/07/20 05:56:47
@@ -23,6 +23,7 @@
 #undef USE_PTHREAD_SERIALIZE
 
 #undef READDIR_IS_THREAD_SAFE
+#undef GETHOSTBYNAME_IS_THREAD_SAFE
 
 #undef NEED_RLIM_T
 #undef USEBCOPY
Index: network_io/unix/sa_common.c
===================================================================
RCS file: /home/cvs/apr/network_io/unix/sa_common.c,v
retrieving revision 1.34
diff -u -r1.34 sa_common.c
--- network_io/unix/sa_common.c	2001/05/02 02:54:11	1.34
+++ network_io/unix/sa_common.c	2001/07/20 05:56:47
@@ -77,6 +77,15 @@
 #define SET_H_ERRNO(newval) h_errno = (newval)
 #endif
 
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R)
+/* This is the maximum size that may be returned from the reentrant
+ * gethostbyname_r function.  If the system tries to use more, it
+ * should return ERANGE.
+ */
+#define GETHOSTBYNAME_BUFLEN 512
+#endif
+
 APR_DECLARE(apr_status_t) apr_sockaddr_port_set(apr_sockaddr_t *sockaddr,
                                        apr_port_t port)
 {
@@ -380,6 +389,12 @@
         struct hostent *hp;
         apr_sockaddr_t *cursa;
         int curaddr;
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R)
+        char tmp[GETHOSTBYNAME_BUFLEN];
+        int hosterror;
+        struct hostent hs;
+#endif
 
         if (family == APR_UNSPEC) {
             family = APR_INET; /* we don't support IPv6 here */
@@ -395,11 +410,22 @@
         }
         else {
 #endif
+#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R)
+        hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, 
+                             &hosterror);
+#else
         hp = gethostbyname(hostname);
+#endif
 
         if (!hp)  {
 #ifdef WIN32
             apr_get_netos_error();
+#elif APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
+    defined(HAVE_GETHOSTBYNAME_R)
+            /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be
+             * bumped. */
+            return (hosterror + APR_OS_START_SYSERR);
 #else
             return (h_errno + APR_OS_START_SYSERR);
 #endif
@@ -412,7 +438,7 @@
         while (hp->h_addr_list[curaddr]) {
             cursa->next = apr_pcalloc(p, sizeof(apr_sockaddr_t));
             cursa = cursa->next;
-            save_addrinfo(p, cursa, *(struct in_addr *)hp->h_addr_list[curaddr], 
+            save_addrinfo(p, cursa, *(struct in_addr *)hp->h_addr_list[curaddr],
                           port);
             ++curaddr;
         }