Commit 88c5c63f authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

multi_socket: react on socket close immediately

As a remedy to the problem when a socket gets closed and a new one is
opened with the same file descriptor number and as a result
multi.c:singlesocket() doesn't detect the difference, the new function
Curl_multi_closed() gets told when a socket is closed so that it can be
removed from the socket hash. When the old one has been removed, a new
socket should be detected fine by the singlesocket() on next invoke.

Bug: http://curl.haxx.se/bug/view.cgi?id=1248
Reported-by: Erik Johansson
parent a9f5ad0e
Loading
Loading
Loading
Loading
+8 −2
Original line number Original line Diff line number Diff line
@@ -1251,7 +1251,13 @@ int Curl_closesocket(struct connectdata *conn,
    else
    else
      return conn->fclosesocket(conn->closesocket_client, sock);
      return conn->fclosesocket(conn->closesocket_client, sock);
  }
  }
  return sclose(sock);
  sclose(sock);

  if(conn)
    /* tell the multi-socket code about this */
    Curl_multi_closed(conn, sock);

  return 0;
}
}


/*
/*
+33 −0
Original line number Original line Diff line number Diff line
@@ -2051,6 +2051,39 @@ static void singlesocket(struct Curl_multi *multi,
  easy->numsocks = num;
  easy->numsocks = num;
}
}


/*
 * Curl_multi_closed()
 *
 * Used by the connect code to tell the multi_socket code that one of the
 * sockets we were using have just been closed.  This function will then
 * remove it from the sockethash for this handle to make the multi_socket API
 * behave properly, especially for the case when libcurl will create another
 * socket again and it gets the same file descriptor number.
 */

void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
{
  struct Curl_multi *multi = conn->data->multi;
  if(multi) {
    /* this is set if this connection is part of a handle that is added to
       a multi handle, and only then this is necessary */
    struct Curl_sh_entry *entry =
      Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));

    if(entry) {
      if(multi->socket_cb)
        multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
                         multi->socket_userp,
                         entry->socketp);

      /* now remove it from the socket hash */
      sh_delentry(multi->sockhash, s);
    }
  }
}



/*
/*
 * add_next_timeout()
 * add_next_timeout()
 *
 *
+12 −0
Original line number Original line Diff line number Diff line
@@ -83,4 +83,16 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);


/*
 * Curl_multi_closed()
 *
 * Used by the connect code to tell the multi_socket code that one of the
 * sockets we were using have just been closed.  This function will then
 * remove it from the sockethash for this handle to make the multi_socket API
 * behave properly, especially for the case when libcurl will create another
 * socket again and it gets the same file descriptor number.
 */

void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);

#endif /* HEADER_CURL_MULTIIF_H */
#endif /* HEADER_CURL_MULTIIF_H */