I wrote a fix for part of libcurl's "known bug #62" so that timeouts set by 
CURLOPT_TIMEOUT will be reported with curl_multi_timeout calls. This is needed 
by a product we are developing, in order to make use of curl's timeout 
framework. 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?

(Release of patch has been approved by the company)

Thanks,

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