Unverified Commit e3a53e3e authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

conncache: use conn->data to know if a transfer owns it

- make sure an already "owned" connection isn't returned unless
  multiplexed.

- clear ->data when returning the connection to the cache again

Regression since 7.62.0 (probably in commit 1b76c389)

Bug: https://curl.haxx.se/mail/lib-2019-03/0064.html

Closes #3686
parent 76cc14ba
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -433,6 +433,7 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
    data->multi->maxconnects;
  struct connectdata *conn_candidate = NULL;

  conn->data = NULL; /* no owner anymore */
  if(maxconnects > 0 &&
     Curl_conncache_size(data) > maxconnects) {
    infof(data, "Connection cache is full, closing the oldest one.\n");
@@ -476,7 +477,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
  while(curr) {
    conn = curr->ptr;

    if(!CONN_INUSE(conn)) {
    if(!CONN_INUSE(conn) && !conn->data) {
      /* Set higher score for the age passed since the connection was used */
      score = Curl_timediff(now, conn->now);

@@ -534,7 +535,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
    while(curr) {
      conn = curr->ptr;

      if(!CONN_INUSE(conn)) {
      if(!CONN_INUSE(conn) && !conn->data) {
        /* Set higher score for the age passed since the connection was used */
        score = Curl_timediff(now, conn->now);

+8 −5
Original line number Diff line number Diff line
@@ -975,7 +975,7 @@ static bool extract_if_dead(struct connectdata *conn,
                            struct Curl_easy *data)
{
  size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
  if(!pipeLen && !CONN_INUSE(conn)) {
  if(!pipeLen && !CONN_INUSE(conn) && !conn->data) {
    /* The check for a dead socket makes sense only if there are no
       handles in pipeline and the connection isn't already marked in
       use */
@@ -1287,14 +1287,15 @@ ConnectionExists(struct Curl_easy *data,
        }
      }

      if(!canpipe && CONN_INUSE(check))
      if(!canpipe && check->data)
        /* this request can't be pipelined but the checked connection is
           already in use so we skip it */
        continue;

      if(CONN_INUSE(check) && (check->data->multi != needle->data->multi))
        /* this could be subject for pipeline/multiplex use, but only
           if they belong to the same multi handle */
      if(CONN_INUSE(check) && check->data &&
         (check->data->multi != needle->data->multi))
        /* this could be subject for pipeline/multiplex use, but only if they
           belong to the same multi handle */
        continue;

      if(needle->localdev || needle->localport) {
@@ -3420,6 +3421,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
  CURLcode result = CURLE_OK;
  timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);

  DEBUGASSERT(conn);
  DEBUGASSERT(data);
  /*************************************************************
   * Resolve the name of the server or proxy
   *************************************************************/