From c33aee1667bd037068674bd354ffd0feb1d13de1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 27 Apr 2011 13:07:49 +0200 Subject: [PATCH] treaded-resolver: better error messages 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 | 1 + lib/asyn-thread.c | 41 ++++++++++++++----- m4/curl-functions.m4 | 95 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index ba09f07b44..0a155eb37a 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index be3b2b51e3..689eb95835 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -64,6 +64,12 @@ #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; diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4 index 6067abf964..ec57b54236 100644 --- a/m4/curl-functions.m4 +++ b/m4/curl-functions.m4 @@ -5,7 +5,7 @@ # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # -# Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. +# Copyright (C) 1998 - 2011, Daniel Stenberg, , 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 -------------------------------------------------