On Tuesday 12 May 2009 11:59:13 pm Yang Tse wrote:
> 2009/5/13, Luke Dashjr wrote:
> > [...] Is this patch acceptable as-is, or does anyone have any
> > suggestions/needs for revision before it can be merged into the next
> > version of libcurl?
>
> First comments come directly from the compiler. Better first fix all
> errors and warnings...

Whoops, I guess I forgot to test that last-minute safety check. Didn't realize 
libcurl was supposed to be C90 conforming either, that's not the default 
compile flag for me... Anyhow, here's a revised patch with those issues fixed.

On Wednesday 13 May 2009 05:03:13 am Daniel Stenberg wrote:
> I think the fix need to be done differently and possibly it needs a
> somewhat larger take. I'll elaborate on the timeout logic...

This version of my code (I had an earlier O(n) one that just checked every 
easy-handle at curl_multi_timeout call) does use the splay tree. I noticed 
that the multi timeouts were only ever 1ms or disabled, so this new function 
is run in the cases where it would have been disabled only. Therefore, the 1ms 
timeouts always should override the user-defined timeout which only comes into 
action when there would be no other timeout set. Or at least that was what I 
tried to do-- did I miss something?

Luke

Index: lib/multi.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/multi.c,v
retrieving revision 1.198
diff -u -r1.198 multi.c
--- lib/multi.c	11 May 2009 07:53:38 -0000	1.198
+++ lib/multi.c	12 May 2009 22:37:02 -0000
@@ -887,6 +887,31 @@
   return CURLM_OK;
 }
 
+static void update_timeout(struct SessionHandle *data)
+{
+  struct timeval now = Curl_tvnow();
+  struct timeval start = data->req.start;
+  if (!start.tv_secs && !start.tv_usecs)
+  {
+    // FIXME: Should we recalculate timeout again later?
+    Curl_expire(data, 0);
+    return;
+  }
+
+  long timeout = data->set.timeout;
+  long passed = curlx_tvdiff(now, start);
+  if (passed > timeout) {
+    // Timeout occurs in the past
+    // FIXME: what if the timeout hasn't be processed yet?
+    Curl_expire(data, 0);
+    return;
+  }
+  --passed;  // round any sub-ms delay up
+
+  long remaining = timeout - passed;
+  Curl_expire(data, remaining);
+}
+
 static CURLMcode multi_runsingle(struct Curl_multi *multi,
                                  struct Curl_one_easy *easy)
 {
@@ -936,6 +961,7 @@
       easy->result=Curl_pretransfer(easy->easy_handle);
 
       if(CURLE_OK == easy->result) {
+        update_timeout(easy->easy_handle);
         /* after init, go CONNECT */
         multistate(easy, CURLM_STATE_CONNECT);
         result = CURLM_CALL_MULTI_PERFORM;
@@ -1537,6 +1563,8 @@
          splay tree */
       tv->tv_sec = 0;
       tv->tv_usec = 0;
+
+      update_timeout(d);
     }
 
   } while(t);
@@ -1909,6 +1937,8 @@
         /* get the socket(s) and check if the state has been changed since
            last */
         singlesocket(multi, data->set.one_easy);
+
+        update_timeout(data);
     }
 
     /* Check if there's one (more) expired timer to deal with! This function

Reply via email to