aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/multi.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 5a5470246..13915c120 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -929,6 +929,7 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
}
static CURLMcode multi_runsingle(struct Curl_multi *multi,
+ struct timeval now,
struct Curl_one_easy *easy)
{
struct Curl_message *msg = NULL;
@@ -940,6 +941,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLMcode result = CURLM_OK;
struct SingleRequest *k;
struct SessionHandle *data;
+ long timeout_ms;
if(!GOOD_EASY_HANDLE(easy->easy_handle))
return CURLM_BAD_EASY_HANDLE;
@@ -974,6 +976,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Make sure we set the connection's current owner */
easy->easy_conn->data = data;
+ if(easy->easy_conn && (easy->state >= CURLM_STATE_CONNECT)) {
+ /* we need to wait for the connect state as only then is the
+ start time stored */
+
+ timeout_ms = Curl_timeleft(easy->easy_conn, &now,
+ easy->state <= CURLM_STATE_WAITDO);
+
+ if(timeout_ms < 0) {
+ /* Handle timed out */
+ easy->result = CURLE_OPERATION_TIMEDOUT;
+ multistate(easy, CURLM_STATE_COMPLETED);
+ break;
+ }
+ }
+
switch(easy->state) {
case CURLM_STATE_INIT:
/* init this transfer. */
@@ -1385,7 +1402,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if( (data->set.max_send_speed > 0) &&
(data->progress.ulspeed > data->set.max_send_speed) ) {
int buffersize;
- long timeout_ms;
multistate(easy, CURLM_STATE_TOOFAST);
@@ -1402,7 +1418,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if( (data->set.max_recv_speed > 0) &&
(data->progress.dlspeed > data->set.max_recv_speed) ) {
int buffersize;
- long timeout_ms;
multistate(easy, CURLM_STATE_TOOFAST);
@@ -1666,7 +1681,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
}
do
- result = multi_runsingle(multi, easy);
+ result = multi_runsingle(multi, now, easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(easy->easy_handle->set.wildcardmatch) {
@@ -2032,6 +2047,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
CURLMcode result = CURLM_OK;
struct SessionHandle *data = NULL;
struct Curl_tree *t;
+ struct timeval now = Curl_tvnow();
if(checkall) {
struct Curl_one_easy *easyp;
@@ -2086,7 +2102,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
do
- result = multi_runsingle(multi, data->set.one_easy);
+ result = multi_runsingle(multi, now, data->set.one_easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(data->set.one_easy->easy_conn)
@@ -2106,18 +2122,23 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
}
}
+ now.tv_usec += 40000; /* compensate for bad precision timers that might've
+ triggered too early */
+ if(now.tv_usec > 1000000) {
+ now.tv_sec++;
+ now.tv_usec -= 1000000;
+ }
+
/*
* The loop following here will go on as long as there are expire-times left
* to process in the splay and 'data' will be re-assigned for every expired
* handle we deal with.
*/
do {
- struct timeval now;
-
/* the first loop lap 'data' can be NULL */
if(data) {
do
- result = multi_runsingle(multi, data->set.one_easy);
+ result = multi_runsingle(multi, now, data->set.one_easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(CURLM_OK >= result)
@@ -2129,16 +2150,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* Check if there's one (more) expired timer to deal with! This function
extracts a matching node if there is one */
- now = Curl_tvnow();
- now.tv_usec += 40000; /* compensate for bad precision timers */
- if(now.tv_usec > 1000000) {
- now.tv_sec++;
- now.tv_usec -= 1000000;
- }
-
multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
- if(t)
+ if(t) {
+ data = t->payload; /* assign this for next loop */
(void)add_next_timeout(now, multi, t->payload);
+ }
} while(t);
@@ -2273,12 +2289,22 @@ CURLMcode curl_multi_timeout(CURLM *multi_handle,
static int update_timer(struct Curl_multi *multi)
{
long timeout_ms;
+
if(!multi->timer_cb)
return 0;
- if( multi_timeout(multi, &timeout_ms) != CURLM_OK )
+ if(multi_timeout(multi, &timeout_ms)) {
return -1;
- if( timeout_ms < 0 )
+ }
+ if( timeout_ms < 0 ) {
+ static const struct timeval none={0,0};
+ if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
+ multi->timer_lastcall = none;
+ /* there's no timeout now but there was one previously, tell the app to
+ disable it */
+ return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
+ }
return 0;
+ }
/* When multi_timeout() is done, multi->timetree points to the node with the
* timeout we got the (relative) time-out time for. We can thus easily check
@@ -2564,10 +2590,6 @@ void Curl_expire(struct SessionHandle *data, long milli)
}
*nowp = set;
-#if 0
- infof(data, "Expire at %ld / %ld (%ldms) %p\n",
- (long)nowp->tv_sec, (long)nowp->tv_usec, milli, data);
-#endif
data->state.timenode.payload = data;
multi->timetree = Curl_splayinsert(*nowp,
multi->timetree,