Skip to content

Commit

Permalink
multi: timeout handles even without connection
Browse files Browse the repository at this point in the history
When there is a "change" in a multi handle and pending handles are moved
back to the main list to be retested if they can proceed further (for
example a previous transfer completed or a connection has a confirmed
multiplexed state), the timeout check in multi_runsingle() would not
trigger because it required an established connection.

This could make a pending tranfer go back to pending state even though
it had been "in progress" for a longer time than permitted. By removing
the requirement for an associated connection, the timeout check will be
done proper even for transfers that has not yet been assigned one.

Fixes #13227
Reported-by: Rahul Krishna M
  • Loading branch information
bagder committed Apr 4, 2024
1 parent a15342d commit 757d80e
Showing 1 changed file with 7 additions and 19 deletions.
26 changes: 7 additions & 19 deletions lib/multi.c
Expand Up @@ -1882,23 +1882,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
return CURLM_INTERNAL_ERROR;
}

if(data->conn &&
(data->mstate >= MSTATE_CONNECT) &&
(data->mstate < MSTATE_COMPLETED)) {
/* Check for overall operation timeout here but defer handling the
* connection timeout to later, to allow for a connection to be set up
* in the window since we last checked timeout. This prevents us
* tearing down a completed connection in the case where we were slow
* to check the timeout (e.g. process descheduled during this loop).
* We set connect_timeout=FALSE to do this. */

/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
/* Skip the statemachine and go directly to error handling section. */
goto statemachine_end;
}
}
/* Wait for the connect state as only then is the start time stored, but
we must not check already completed handles */
if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) &&
multi_handle_timeout(data, nowp, &stream_error, &result, FALSE))
/* Skip the statemachine and go directly to error handling section. */
goto statemachine_end;

switch(data->mstate) {
case MSTATE_INIT:
Expand Down Expand Up @@ -2570,8 +2559,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
return CURLM_INTERNAL_ERROR;
}

if(data->conn &&
data->mstate >= MSTATE_CONNECT &&
if(data->mstate >= MSTATE_CONNECT &&
data->mstate < MSTATE_DO &&
rc != CURLM_CALL_MULTI_PERFORM &&
!multi_ischanged(multi, false)) {
Expand Down

0 comments on commit 757d80e

Please sign in to comment.