diff --git a/src/net.c b/src/net.c index 1a88155bc..99a47ea18 100644 --- a/src/net.c +++ b/src/net.c @@ -115,6 +115,28 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen, return (ret); } +#ifdef __CYGWIN__ + +const unsigned int MAX_GETADDRINFO_RETRIES = 10; +/* getaddrinfo may not be completely reliable on Windows hosts. Try more than once. */ +int iperf_getaddrinfo(const char *restrict node, + const char *restrict service, + const struct addrinfo *restrict hints, + struct addrinfo **restrict res) +{ + int retvalue = -1; + int i = 0; + while (i++ < MAX_GETADDRINFO_RETRIES) { + retvalue = getaddrinfo(node, service, hints, res); + if (0 == retvalue) break; + sleep(1); /* yield thread */ + fprintf(stderr, "getadddrinfo failed. If iperf still ran successfully, this may be a Windows bug. Please see https://github.com/esnet/iperf/issues/1314 . \n"); + } + return retvalue; +} + +#endif + /* netdial and netannouce code comes from libtask: http://swtch.com/libtask/ * Copyright: http://swtch.com/libtask/COPYRIGHT */ @@ -131,7 +153,7 @@ create_socket(int domain, int proto, const char *local, const char *bind_dev, in memset(&hints, 0, sizeof(hints)); hints.ai_family = domain; hints.ai_socktype = proto; - if ((gerror = getaddrinfo(local, NULL, &hints, &local_res)) != 0) + if ((gerror = iperf_getaddrinfo(local, NULL, &hints, &local_res)) != 0) return -1; } @@ -139,7 +161,7 @@ create_socket(int domain, int proto, const char *local, const char *bind_dev, in hints.ai_family = domain; hints.ai_socktype = proto; snprintf(portstr, sizeof(portstr), "%d", port); - if ((gerror = getaddrinfo(server, portstr, &hints, &server_res)) != 0) { + if ((gerror = iperf_getaddrinfo(server, portstr, &hints, &server_res)) != 0) { if (local) freeaddrinfo(local_res); return -1; @@ -283,7 +305,7 @@ netannounce(int domain, int proto, const char *local, const char *bind_dev, int } hints.ai_socktype = proto; hints.ai_flags = AI_PASSIVE; - if ((gerror = getaddrinfo(local, portstr, &hints, &res)) != 0) + if ((gerror = iperf_getaddrinfo(local, portstr, &hints, &res)) != 0) return -1; s = socket(res->ai_family, proto, 0); diff --git a/src/net.h b/src/net.h index f0e1b4f98..948574153 100644 --- a/src/net.h +++ b/src/net.h @@ -27,6 +27,14 @@ #ifndef __NET_H #define __NET_H +#ifdef __CYGWIN__ +int iperf_getaddrinfo(const char *restrict node, + const char *restrict service, + const struct addrinfo *restrict hints, + struct addrinfo **restrict res); +#else +#define iperf_getaddrinfo getaddrinfo +#endif int timeout_connect(int s, const struct sockaddr *name, socklen_t namelen, int timeout); int create_socket(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, struct addrinfo **server_res_out); int netdial(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, int timeout);