--- src/lib/network.c.orig Sun Oct 28 02:09:24 2007 +++ src/lib/network.c Tue Nov 27 12:27:18 2007 @@ -107,55 +107,69 @@ const struct ip_addr *my_ip) { union sockaddr_union so; - int fd, ret, opt = 1; + int fd, ret, opt = 1, retries = 10; if (my_ip != NULL && ip->family != my_ip->family) { i_warning("net_connect_ip(): ip->family != my_ip->family"); my_ip = NULL; } - /* create the socket */ - memset(&so, 0, sizeof(so)); - so.sin.sin_family = ip->family; - fd = socket(ip->family, SOCK_STREAM, 0); - - if (fd == -1) { - i_error("socket() failed: %m"); - return -1; - } - - /* set socket options */ - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); - net_set_nonblock(fd, TRUE); + while (retries > 0) + { + /* create the socket */ + memset(&so, 0, sizeof(so)); + so.sin.sin_family = ip->family; + fd = socket(ip->family, SOCK_STREAM, 0); - /* set our own address */ - if (my_ip != NULL) { - sin_set_ip(&so, my_ip); - if (bind(fd, &so.sa, SIZEOF_SOCKADDR(so)) == -1) { - /* failed, set it back to INADDR_ANY */ - i_error("bind(%s) failed: %m", net_ip2addr(my_ip)); - close_keep_errno(fd); + if (fd == -1) { + i_error("socket() failed: %m"); return -1; } - } - - /* connect */ - sin_set_ip(&so, ip); - sin_set_port(&so, port); - ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); - + + /* set socket options */ + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); + net_set_nonblock(fd, TRUE); + + /* set our own address */ + if (my_ip != NULL) { + sin_set_ip(&so, my_ip); + if (bind(fd, &so.sa, SIZEOF_SOCKADDR(so)) == -1) { + /* failed, set it back to INADDR_ANY */ + i_error("bind(%s) failed: %m", net_ip2addr(my_ip)); + close_keep_errno(fd); + return -1; + } + } + + /* connect */ + sin_set_ip(&so, ip); + sin_set_port(&so, port); + ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); + + if (ret < 0 && (errno == EADDRINUSE || errno == EACCES)) + { + /* log the error */ + i_error("connect() failed: %m, %d more retries", retries); + close_keep_errno(fd); + retries--; + continue; + } #ifndef WIN32 - if (ret < 0 && errno != EINPROGRESS) + else if (ret < 0 && errno != EINPROGRESS) #else - if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + else if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) #endif - { - close_keep_errno(fd); - return -1; + { + close_keep_errno(fd); + return -1; + } + + return fd; } - return fd; + /* Retry count exhausted */ + return -1; } int net_connect_unix(const char *path)