treaded-resolver: better error messages
authorDaniel Stenberg <daniel@haxx.se>
Wed, 27 Apr 2011 11:07:49 +0000 (13:07 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 28 Apr 2011 13:25:03 +0000 (15:25 +0200)
Now use gai_strerror() to get proper error messages when getaddrinfo()
has failed. Detect the function in configure.

Code based on work and suggestions by Jeff Pohlmeyer and Guenter Knauf

configure.ac
lib/asyn-thread.c
m4/curl-functions.m4

index ba09f07..0a155eb 100644 (file)
@@ -2517,6 +2517,7 @@ CURL_CHECK_FUNC_FREEIFADDRS
 CURL_CHECK_FUNC_FSETXATTR
 CURL_CHECK_FUNC_FTRUNCATE
 CURL_CHECK_FUNC_GETADDRINFO
+CURL_CHECK_FUNC_GAI_STRERROR
 CURL_CHECK_FUNC_GETHOSTBYADDR
 CURL_CHECK_FUNC_GETHOSTBYADDR_R
 CURL_CHECK_FUNC_GETHOSTBYNAME
index be3b2b5..689eb95 100644 (file)
 #define in_addr_t unsigned long
 #endif
 
+#ifdef HAVE_GETADDRINFO
+#  define RESOLVER_ENOMEM  EAI_MEMORY
+#else
+#  define RESOLVER_ENOMEM  ENOMEM
+#endif
+
 #include "urldata.h"
 #include "sendf.h"
 #include "hostip.h"
@@ -281,9 +287,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
 
   if(rc != 0) {
-    tsd->sock_error = SOCKERRNO;
+    tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
     if(tsd->sock_error == 0)
-      tsd->sock_error = ENOMEM;
+      tsd->sock_error = RESOLVER_ENOMEM;
   }
 
   Curl_mutex_acquire(tsd->mtx);
@@ -307,7 +313,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
   if(!tsd->res) {
     tsd->sock_error = SOCKERRNO;
     if(tsd->sock_error == 0)
-      tsd->sock_error = ENOMEM;
+      tsd->sock_error = RESOLVER_ENOMEM;
   }
 
   Curl_mutex_acquire(tsd->mtx);
@@ -355,7 +361,7 @@ static bool init_resolve_thread (struct connectdata *conn,
                                  const struct addrinfo *hints)
 {
   struct thread_data *td = calloc(1, sizeof(struct thread_data));
-  int err = ENOMEM;
+  int err = RESOLVER_ENOMEM;
 
   conn->async.os_specific = (void*) td;
   if(!td)
@@ -409,6 +415,24 @@ static bool init_resolve_thread (struct connectdata *conn,
   return FALSE;
 }
 
+/*
+ * resolver_error() calls failf() with the appropriate message after a resolve
+ * error
+ */
+
+static void resolver_error(struct connectdata *conn, const char *host_or_proxy)
+{
+  failf(conn->data, "Could not resolve %s: %s; %s", host_or_proxy,
+        conn->async.hostname,
+#ifdef HAVE_GAI_STRERROR
+        /* NetWare doesn't have gai_strerror and on Windows it isn't deemed
+           thread-safe */
+        gai_strerror(conn->async.status)
+#else
+        Curl_strerror(conn, conn->async.status);
+#endif
+    );
+}
 
 /*
  * Curl_resolver_wait_resolv()
@@ -443,13 +467,11 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   if(!conn->async.dns) {
     /* a name was not resolved */
     if(conn->bits.httpproxy) {
-      failf(data, "Could not resolve proxy: %s; %s",
-            conn->async.hostname, Curl_strerror(conn, conn->async.status));
+      resolver_error(conn, "proxy");
       rc = CURLE_COULDNT_RESOLVE_PROXY;
     }
     else {
-      failf(data, "Could not resolve host: %s; %s",
-            conn->async.hostname, Curl_strerror(conn, conn->async.status));
+      resolver_error(conn, "host");
       rc = CURLE_COULDNT_RESOLVE_HOST;
     }
   }
@@ -490,8 +512,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
     destroy_async_data(&conn->async);
 
     if(!conn->async.dns) {
-      failf(data, "Could not resolve host: %s; %s",
-            conn->host.name, Curl_strerror(conn, conn->async.status));
+      resolver_error(conn, "host");
       return CURLE_COULDNT_RESOLVE_HOST;
     }
     *entry = conn->async.dns;
index 6067abf..ec57b54 100644 (file)
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -2314,6 +2314,99 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTBYADDR], [
   fi
 ])
 
+dnl CURL_CHECK_FUNC_GAI_STRERROR
+dnl -------------------------------------------------
+dnl Verify if gai_strerror is available, prototyped,
+dnl and can be compiled. If all of these are true,
+dnl and usage has not been previously disallowed with
+dnl shell variable curl_disallow_gai_strerror, then
+dnl HAVE_GAI_STRERROR will be defined.
+
+AC_DEFUN([CURL_CHECK_FUNC_GAI_STRERROR], [
+  AC_REQUIRE([CURL_INCLUDES_WINSOCK2])dnl
+  AC_REQUIRE([CURL_INCLUDES_NETDB])dnl
+  #
+  tst_links_gai_strerror="unknown"
+  tst_proto_gai_strerror="unknown"
+  tst_compi_gai_strerror="unknown"
+  tst_allow_gai_strerror="unknown"
+  #
+  AC_MSG_CHECKING([if gai_strerror can be linked])
+  AC_LINK_IFELSE([
+    AC_LANG_PROGRAM([[
+      $curl_includes_winsock2
+      $curl_includes_netdb
+    ]],[[
+      if(0 != gai_strerror(0))
+        return 1;
+    ]])
+  ],[
+    AC_MSG_RESULT([yes])
+    tst_links_gai_strerror="yes"
+  ],[
+    AC_MSG_RESULT([no])
+    tst_links_gai_strerror="no"
+  ])
+  #
+  if test "$tst_links_gai_strerror" = "yes"; then
+    AC_MSG_CHECKING([if gai_strerror is prototyped])
+    AC_EGREP_CPP([gai_strerror],[
+      $curl_includes_winsock2
+      $curl_includes_netdb
+    ],[
+      AC_MSG_RESULT([yes])
+      tst_proto_gai_strerror="yes"
+    ],[
+      AC_MSG_RESULT([no])
+      tst_proto_gai_strerror="no"
+    ])
+  fi
+  #
+  if test "$tst_proto_gai_strerror" = "yes"; then
+    AC_MSG_CHECKING([if gai_strerror is compilable])
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM([[
+        $curl_includes_winsock2
+        $curl_includes_netdb
+      ]],[[
+        if(0 != gai_strerror(0))
+          return 1;
+      ]])
+    ],[
+      AC_MSG_RESULT([yes])
+      tst_compi_gai_strerror="yes"
+    ],[
+      AC_MSG_RESULT([no])
+      tst_compi_gai_strerror="no"
+    ])
+  fi
+  #
+  if test "$tst_compi_gai_strerror" = "yes"; then
+    AC_MSG_CHECKING([if gai_strerror usage allowed])
+    if test "x$curl_disallow_gai_strerror" != "xyes"; then
+      AC_MSG_RESULT([yes])
+      tst_allow_gai_strerror="yes"
+    else
+      AC_MSG_RESULT([no])
+      tst_allow_gai_strerror="no"
+    fi
+  fi
+  #
+  AC_MSG_CHECKING([if gai_strerror might be used])
+  if test "$tst_links_gai_strerror" = "yes" &&
+     test "$tst_proto_gai_strerror" = "yes" &&
+     test "$tst_compi_gai_strerror" = "yes" &&
+     test "$tst_allow_gai_strerror" = "yes"; then
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_GAI_STRERROR, 1,
+      [Define to 1 if you have the gai_strerror function.])
+    ac_cv_func_gai_strerror="yes"
+  else
+    AC_MSG_RESULT([no])
+    ac_cv_func_gai_strerror="no"
+  fi
+])
+
 
 dnl CURL_CHECK_FUNC_GETHOSTBYADDR_R
 dnl -------------------------------------------------