Commit 0fd439eb authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

multi_runsingle: don't timeout completed handles

The generic timeout code must not check easy handles that are already
completed. Going to completed (again) within there risked decreasing the
number of alive handles again and thus it could go negative.

This regression bug was added in 7.21.2 in commit ca10e28f
parent 012f9b7f
Loading
Loading
Loading
Loading
+24 −21
Original line number Original line Diff line number Diff line
@@ -68,24 +68,25 @@ struct Curl_message {
   well!
   well!
*/
*/
typedef enum {
typedef enum {
  CURLM_STATE_INIT,        /* start in this state */
  CURLM_STATE_INIT,        /* 0 - start in this state */
  CURLM_STATE_CONNECT,     /* resolve/connect has been sent off */
  CURLM_STATE_CONNECT,     /* 1 - resolve/connect has been sent off */
  CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
  CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */
  CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
  CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */
  CURLM_STATE_WAITPROXYCONNECT, /* awaiting proxy CONNECT to finalize */
  CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */
  CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect phase */
  CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect
  CURLM_STATE_WAITDO,      /* wait for our turn to send the request */
                               phase */
  CURLM_STATE_DO,          /* start send off the request (part 1) */
  CURLM_STATE_WAITDO,      /* 6 - wait for our turn to send the request */
  CURLM_STATE_DOING,       /* sending off the request (part 1) */
  CURLM_STATE_DO,          /* 7 - start send off the request (part 1) */
  CURLM_STATE_DO_MORE,     /* send off the request (part 2) */
  CURLM_STATE_DOING,       /* 8 - sending off the request (part 1) */
  CURLM_STATE_DO_DONE,     /* done sending off request */
  CURLM_STATE_DO_MORE,     /* 9 - send off the request (part 2) */
  CURLM_STATE_WAITPERFORM, /* wait for our turn to read the response */
  CURLM_STATE_DO_DONE,     /* 10 - done sending off request */
  CURLM_STATE_PERFORM,     /* transfer data */
  CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */
  CURLM_STATE_TOOFAST,     /* wait because limit-rate exceeded */
  CURLM_STATE_PERFORM,     /* 12 - transfer data */
  CURLM_STATE_DONE,        /* post data transfer operation */
  CURLM_STATE_TOOFAST,     /* 13 - wait because limit-rate exceeded */
  CURLM_STATE_COMPLETED,   /* operation complete */
  CURLM_STATE_DONE,        /* 14 - post data transfer operation */
  CURLM_STATE_MSGSENT,     /* the operation complete message is sent */
  CURLM_STATE_COMPLETED,   /* 15 - operation complete */
  CURLM_STATE_LAST /* not a true state, never use this */
  CURLM_STATE_MSGSENT,     /* 16 - the operation complete message is sent */
  CURLM_STATE_LAST         /* 17 - not a true state, never use this */
} CURLMstate;
} CURLMstate;


/* we support N sockets per easy handle. Set the corresponding bit to what
/* we support N sockets per easy handle. Set the corresponding bit to what
@@ -977,9 +978,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
      /* Make sure we set the connection's current owner */
      /* Make sure we set the connection's current owner */
      easy->easy_conn->data = data;
      easy->easy_conn->data = data;


    if(easy->easy_conn && (easy->state >= CURLM_STATE_CONNECT)) {
    if(easy->easy_conn &&
      /* we need to wait for the connect state as only then is the
       (easy->state >= CURLM_STATE_CONNECT) &&
         start time stored */
       (easy->state < CURLM_STATE_COMPLETED)) {
      /* we need to wait for the connect state as only then is the start time
         stored, but we must not check already completed handles */


      timeout_ms = Curl_timeleft(easy->easy_conn, &now,
      timeout_ms = Curl_timeleft(easy->easy_conn, &now,
                                 (easy->state <= CURLM_STATE_WAITDO)?
                                 (easy->state <= CURLM_STATE_WAITDO)?