Reduce to 20 seconds the time allowed to set SO_REUSEADDR option on sockfilt listener socket.
Log some more error descriptions.
This commit is contained in:
parent
0d722204c3
commit
c9eb41c056
@ -143,7 +143,7 @@ static void sigpipe_handler(int sig)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char use_ipv6=FALSE;
|
bool use_ipv6=FALSE;
|
||||||
unsigned short port = DEFAULT_PORT;
|
unsigned short port = DEFAULT_PORT;
|
||||||
unsigned short connectport = 0; /* if non-zero, we activate this mode */
|
unsigned short connectport = 0; /* if non-zero, we activate this mode */
|
||||||
|
|
||||||
@ -427,25 +427,43 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
|
|||||||
#endif /* ENABLE_IPV6 */
|
#endif /* ENABLE_IPV6 */
|
||||||
int flag = 1;
|
int flag = 1;
|
||||||
int rc;
|
int rc;
|
||||||
int maxretr = 12;
|
int totdelay = 0;
|
||||||
int delay= 10;
|
int maxretr = 10;
|
||||||
|
int delay= 20;
|
||||||
|
int attempt = 0;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
do {
|
||||||
(void *)&flag, sizeof(flag));
|
attempt++;
|
||||||
while ((rc < 0) && maxretr) {
|
|
||||||
maxretr--;
|
|
||||||
go_sleep(delay);
|
|
||||||
delay *= 2; /* double the sleep for next attempt */
|
|
||||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||||
(void *)&flag, sizeof(flag));
|
(void *)&flag, sizeof(flag));
|
||||||
}
|
if(rc) {
|
||||||
if (rc < 0) {
|
error = SOCKERRNO;
|
||||||
perror("setsockopt(SO_REUSEADDR)");
|
if(maxretr) {
|
||||||
|
rc = wait_ms(delay);
|
||||||
|
if(rc) {
|
||||||
|
/* should not happen */
|
||||||
|
error = SOCKERRNO;
|
||||||
|
logmsg("wait_ms() failed: (%d) %s", error, strerror(error));
|
||||||
|
sclose(sock);
|
||||||
|
return CURL_SOCKET_BAD;
|
||||||
|
}
|
||||||
|
totdelay += delay;
|
||||||
|
delay *= 2; /* double the sleep for next attempt */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(rc && maxretr--);
|
||||||
|
|
||||||
|
if(rc) {
|
||||||
|
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error: (%d) %s",
|
||||||
|
attempt, totdelay, error, strerror(error));
|
||||||
|
logmsg("Continuing anyway...");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
if(!use_ipv6) {
|
if(!use_ipv6) {
|
||||||
#endif
|
#endif
|
||||||
|
memset(&me, 0, sizeof(me));
|
||||||
me.sin_family = AF_INET;
|
me.sin_family = AF_INET;
|
||||||
me.sin_addr.s_addr = INADDR_ANY;
|
me.sin_addr.s_addr = INADDR_ANY;
|
||||||
me.sin_port = htons(*listenport);
|
me.sin_port = htons(*listenport);
|
||||||
@ -453,16 +471,17 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
|
|||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memset(&me6, 0, sizeof(struct sockaddr_in6));
|
memset(&me6, 0, sizeof(me6));
|
||||||
me6.sin6_family = AF_INET6;
|
me6.sin6_family = AF_INET6;
|
||||||
me6.sin6_addr = in6addr_any;
|
me6.sin6_addr = in6addr_any;
|
||||||
me6.sin6_port = htons(*listenport);
|
me6.sin6_port = htons(*listenport);
|
||||||
rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
|
rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_IPV6 */
|
#endif /* ENABLE_IPV6 */
|
||||||
if(rc < 0) {
|
if(rc) {
|
||||||
perror("binding stream socket");
|
error = SOCKERRNO;
|
||||||
logmsg("Error binding socket");
|
logmsg("Error binding socket: (%d) %s", error, strerror(error));
|
||||||
|
sclose(sock);
|
||||||
return CURL_SOCKET_BAD;
|
return CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,16 +494,21 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
|
|||||||
|
|
||||||
if(getsockname(sock, (struct sockaddr *) &add,
|
if(getsockname(sock, (struct sockaddr *) &add,
|
||||||
&socksize)<0) {
|
&socksize)<0) {
|
||||||
logmsg("getsockname() failed with error: %d", SOCKERRNO);
|
error = SOCKERRNO;
|
||||||
|
logmsg("getsockname() failed with error: (%d) %s",
|
||||||
|
error, strerror(error));
|
||||||
|
sclose(sock);
|
||||||
return CURL_SOCKET_BAD;
|
return CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
*listenport = ntohs(add.sin_port);
|
*listenport = ntohs(add.sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start accepting connections */
|
/* start accepting connections */
|
||||||
rc = listen(sock, 4);
|
rc = listen(sock, 5);
|
||||||
if(0 != rc) {
|
if(0 != rc) {
|
||||||
logmsg("listen() failed with error: %d", SOCKERRNO);
|
error = SOCKERRNO;
|
||||||
|
logmsg("listen() failed with error: (%d) %s",
|
||||||
|
error, strerror(error));
|
||||||
sclose(sock);
|
sclose(sock);
|
||||||
return CURL_SOCKET_BAD;
|
return CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
@ -492,28 +516,6 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static curl_socket_t mksock(bool ipv6)
|
|
||||||
{
|
|
||||||
curl_socket_t sock;
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
if(!ipv6)
|
|
||||||
#else
|
|
||||||
(void)ipv6;
|
|
||||||
#endif
|
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
else
|
|
||||||
sock = socket(AF_INET6, SOCK_STREAM, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (CURL_SOCKET_BAD == sock) {
|
|
||||||
perror("opening stream socket");
|
|
||||||
logmsg("Error opening socket");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -616,10 +618,19 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if(!use_ipv6)
|
||||||
|
#endif
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
else
|
||||||
|
sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
sock = mksock(use_ipv6);
|
if(CURL_SOCKET_BAD == sock) {
|
||||||
if (CURL_SOCKET_BAD == sock) {
|
error = SOCKERRNO;
|
||||||
logmsg("Error opening socket: %d", SOCKERRNO);
|
logmsg("Error creating socket: (%d) %s",
|
||||||
|
error, strerror(error));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,8 +663,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif /* ENABLE_IPV6 */
|
#endif /* ENABLE_IPV6 */
|
||||||
if(rc) {
|
if(rc) {
|
||||||
perror("connecting stream socket");
|
error = SOCKERRNO;
|
||||||
logmsg("Error connecting to port %d", port);
|
logmsg("Error connecting to port %d: (%d) %s",
|
||||||
|
port, error, strerror(error));
|
||||||
sclose(sock);
|
sclose(sock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -165,31 +165,60 @@ char *test2file(long testno)
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void go_sleep(long ms)
|
/*
|
||||||
|
* Portable function used for waiting a specific amount of ms.
|
||||||
|
* Waiting indefinitely with this function is not allowed, a
|
||||||
|
* zero or negative timeout value will return immediately.
|
||||||
|
*
|
||||||
|
* Return values:
|
||||||
|
* -1 = system call error, or invalid timeout value
|
||||||
|
* 0 = specified timeout has elapsed
|
||||||
|
*/
|
||||||
|
int wait_ms(int timeout_ms)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_POLL_FINE
|
#if !defined(MSDOS) && !defined(USE_WINSOCK)
|
||||||
/* portable subsecond "sleep" */
|
#ifndef HAVE_POLL_FINE
|
||||||
poll((void *)0, 0, (int)ms);
|
struct timeval pending_tv;
|
||||||
#else
|
|
||||||
/* systems without poll() need other solutions */
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/* Windows offers a millisecond sleep */
|
|
||||||
Sleep(ms);
|
|
||||||
#elif defined(MSDOS)
|
|
||||||
delay(ms);
|
|
||||||
#else
|
|
||||||
/* Other systems must use select() for this */
|
|
||||||
struct timeval timeout;
|
|
||||||
|
|
||||||
timeout.tv_sec = ms/1000;
|
|
||||||
ms = ms%1000;
|
|
||||||
timeout.tv_usec = ms * 1000;
|
|
||||||
|
|
||||||
select(0, NULL, NULL, NULL, &timeout);
|
|
||||||
#endif
|
#endif
|
||||||
|
struct timeval initial_tv;
|
||||||
|
int pending_ms;
|
||||||
|
int error;
|
||||||
#endif
|
#endif
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
if(!timeout_ms)
|
||||||
|
return 0;
|
||||||
|
if(timeout_ms < 0) {
|
||||||
|
SET_SOCKERRNO(EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if defined(MSDOS)
|
||||||
|
delay(timeout_ms);
|
||||||
|
#elif defined(USE_WINSOCK)
|
||||||
|
Sleep(timeout_ms);
|
||||||
|
#else
|
||||||
|
pending_ms = timeout_ms;
|
||||||
|
initial_tv = curlx_tvnow();
|
||||||
|
do {
|
||||||
|
#if defined(HAVE_POLL_FINE)
|
||||||
|
r = poll(NULL, 0, pending_ms);
|
||||||
|
#else
|
||||||
|
pending_tv.tv_sec = pending_ms / 1000;
|
||||||
|
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
|
||||||
|
r = select(0, NULL, NULL, NULL, &pending_tv);
|
||||||
|
#endif /* HAVE_POLL_FINE */
|
||||||
|
if(r != -1)
|
||||||
|
break;
|
||||||
|
error = SOCKERRNO;
|
||||||
|
if(error == EINVAL)
|
||||||
|
break;
|
||||||
|
pending_ms = timeout_ms - (int)curlx_tvdiff(curlx_tvnow(), initial_tv);
|
||||||
|
if(pending_ms <= 0)
|
||||||
|
break;
|
||||||
|
} while(r == -1);
|
||||||
|
#endif /* USE_WINSOCK */
|
||||||
|
if(r)
|
||||||
|
r = -1;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -49,6 +49,6 @@ void win32_cleanup(void);
|
|||||||
/* returns the path name to the test case file */
|
/* returns the path name to the test case file */
|
||||||
char *test2file(long testno);
|
char *test2file(long testno);
|
||||||
|
|
||||||
void go_sleep(long ms);
|
int wait_ms(int timeout_ms);
|
||||||
|
|
||||||
#endif /* __SERVER_UTIL_H */
|
#endif /* __SERVER_UTIL_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user