Date: Thu, 23 Jun 2011 05:23:57 -0500 getaddrinfo() and gethostbyname() use error codes to describe their errors. Pass that error code back to the caller when dns_resolve() fails and the RESOLVE_FAIL_QUIETLY flag is set, so callers can save the diagnosis and print it later: int saved_rerrno = dns_resolve(...); ... if (saved_rerrno) die("resolver failed: %s", dns_strerror(saved_rerrno)); In the ipv4 codepath, we assume that h_errno is never 0 on error. POSIX.1-2004 does not specify whether 0 is a valid value for h_errno, but luckily common practice is for h_errno to be a strictly positive integer (HOST_NOT_FOUND = 1, NO_DATA = 2, NO_RECOVERY = 3, or TRY_AGAIN = 4). If gethostbyname errors out with h_errno == 0 on some platform, just let git die with a message indicating a BUG so the bad assumption can be corrected. Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- This makes saving up errors from a host resolution failure as in v1.7.7-rc0~40^2 (connect: only log if all attempts failed, 2011-08-01) possible. By the way, this series is currently against "maint" for no particular reason and presumably it would conflict with that patch. ;-) I'll be happy to rebase against "master" some time soon. dns-ipv4.c | 7 +++++-- dns-ipv4.h | 5 +++++ dns-ipv6.c | 2 +- dns-ipv6.h | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dns-ipv4.c b/dns-ipv4.c index 911a8569..8820c9e8 100644 --- a/dns-ipv4.c +++ b/dns-ipv4.c @@ -9,8 +9,11 @@ int dns_resolve(const char *host, const char *port, int flags, unsigned int nport; he = gethostbyname(host); - if (!he && (flags & RESOLVE_FAIL_QUIETLY)) - return -1; + if (!he && (flags & RESOLVE_FAIL_QUIETLY)) { + if (!h_errno) + die("BUG: gethostbyname failed but h_errno == 0"); + return h_errno; + } if (!he) die("Unable to look up %s (%s)", host, hstrerror(h_errno)); diff --git a/dns-ipv4.h b/dns-ipv4.h index c5f1778f..6f70d639 100644 --- a/dns-ipv4.h +++ b/dns-ipv4.h @@ -18,6 +18,10 @@ typedef struct ipv4_address resolved_address; enum { RESOLVE_CANONNAME = 1, + /* + * Quietly return an error code instead of exiting on error. + * Callers can use dns_strerror() to get an error string. + */ RESOLVE_FAIL_QUIETLY = 2 }; extern int dns_resolve(const char *host, const char *port, int flags, @@ -63,6 +67,7 @@ static inline int dns_fill_sockaddr_(char *ap, #define dns_addrlen(addr, ai) sizeof((addr).sa) #define dns_canonname(addr, ai) ((ai).he->h_name) +#define dns_strerror(n) hstrerror(n) #define dns_free(ai) do { /* nothing */ } while (0) #endif diff --git a/dns-ipv6.c b/dns-ipv6.c index f2325681..0b0e0602 100644 --- a/dns-ipv6.c +++ b/dns-ipv6.c @@ -41,7 +41,7 @@ int dns_resolve(const char *host, const char *port, int flags, gai = getaddrinfo(host, port, &hints, res); if (gai && (flags & RESOLVE_FAIL_QUIETLY)) - return -1; + return gai; if (gai) die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai)); diff --git a/dns-ipv6.h b/dns-ipv6.h index 16bf84b5..4211c9e2 100644 --- a/dns-ipv6.h +++ b/dns-ipv6.h @@ -26,6 +26,7 @@ extern char *dns_ip_address(const resolved_address *i, #define dns_addrlen(i, ai) ((i)->ai_addrlen) #define dns_canonname(i, ai) ((i)->ai_canonname) +#define dns_strerror(gai) gai_strerror(gai) #define dns_free(ai) freeaddrinfo(ai) #endif -- 1.7.9.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html