Commit c9eb41c0 authored by Yang Tse's avatar Yang Tse
Browse files

Reduce to 20 seconds the time allowed to set SO_REUSEADDR option on sockfilt listener socket.

Log some more error descriptions.
parent 0d722204
Loading
Loading
Loading
Loading
+59 −47
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ static void sigpipe_handler(int sig)
}
#endif

char use_ipv6=FALSE;
bool use_ipv6=FALSE;
unsigned short port = DEFAULT_PORT;
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 */
  int flag = 1;
  int rc;
  int maxretr = 12;
  int delay= 10;
  int totdelay = 0;
  int maxretr = 10;
  int delay= 20;
  int attempt = 0;
  int error = 0;

  do {
    attempt++;
    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
         (void *)&flag, sizeof(flag));
  while ((rc < 0) && maxretr) {
    maxretr--;
    go_sleep(delay);
    if(rc) {
      error = SOCKERRNO;
      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 */
    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
         (void *)&flag, sizeof(flag));
      }
  if (rc < 0) {
    perror("setsockopt(SO_REUSEADDR)");
    }
  } 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
  if(!use_ipv6) {
#endif
    memset(&me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_addr.s_addr = INADDR_ANY;
    me.sin_port = htons(*listenport);
@@ -453,16 +471,17 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
#ifdef ENABLE_IPV6
  }
  else {
    memset(&me6, 0, sizeof(struct sockaddr_in6));
    memset(&me6, 0, sizeof(me6));
    me6.sin6_family = AF_INET6;
    me6.sin6_addr = in6addr_any;
    me6.sin6_port = htons(*listenport);
    rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
  }
#endif /* ENABLE_IPV6 */
  if(rc < 0) {
    perror("binding stream socket");
    logmsg("Error binding socket");
  if(rc) {
    error = SOCKERRNO;
    logmsg("Error binding socket: (%d) %s", error, strerror(error));
    sclose(sock);
    return CURL_SOCKET_BAD;
  }

@@ -475,16 +494,21 @@ static curl_socket_t sockdaemon(curl_socket_t sock,

    if(getsockname(sock, (struct sockaddr *) &add,
                   &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;
    }
    *listenport = ntohs(add.sin_port);
  }

  /* start accepting connections */
  rc = listen(sock, 4);
  rc = listen(sock, 5);
  if(0 != rc) {
    logmsg("listen() failed with error: %d", SOCKERRNO);
    error = SOCKERRNO;
    logmsg("listen() failed with error: (%d) %s",
           error, strerror(error));
    sclose(sock);
    return CURL_SOCKET_BAD;
  }
@@ -492,28 +516,6 @@ static curl_socket_t sockdaemon(curl_socket_t 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[])
{
@@ -616,10 +618,19 @@ int main(int argc, char *argv[])
#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) {
    logmsg("Error opening socket: %d", SOCKERRNO);
    error = SOCKERRNO;
    logmsg("Error creating socket: (%d) %s",
           error, strerror(error));
    return 1;
  }

@@ -652,8 +663,9 @@ int main(int argc, char *argv[])
    }
#endif /* ENABLE_IPV6 */
    if(rc) {
      perror("connecting stream socket");
      logmsg("Error connecting to port %d", port);
      error = SOCKERRNO;
      logmsg("Error connecting to port %d: (%d) %s",
             port, error, strerror(error));
      sclose(sock);
      return 1;
    }
+52 −23
Original line number Diff line number Diff line
@@ -165,31 +165,60 @@ char *test2file(long testno)
  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
  /* portable subsecond "sleep" */
  poll((void *)0, 0, (int)ms);
#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);
#if !defined(MSDOS) && !defined(USE_WINSOCK)
#ifndef HAVE_POLL_FINE
  struct timeval pending_tv;
#endif

  struct timeval initial_tv;
  int pending_ms;
  int error;
#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;
}
+2 −2
Original line number Diff line number Diff line
@@ -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
 * 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 */
char *test2file(long testno);

void go_sleep(long ms);
int wait_ms(int timeout_ms);

#endif  /* __SERVER_UTIL_H */