On Sat, 30 Jan 2010, Daniel Stenberg wrote:
multi interface users of libcurl, this issue may concern you so please bare
with my longish mail and I'll get to the point eventually...
Perhaps my thoughts are best explained by the attached patch, that A) fixes
the bug I mentioned and B) makes CURLM_CALL_MULTI_PERFORM _never_ get returned
by a libcurl function. The obsoleting of that return code in the public API
will not break the ABI anyway, it will just make the looping unnecessary
starting with 7.20.0.
This is what I plan to commit soonish (unless something pops up that speaks
against it), this is just posted here as an explanation and to offer you guys
a chance to try it out independently of everything else if you'd like.
--
/ daniel.haxx.se
Index: docs/libcurl/curl_multi_perform.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_multi_perform.3,v
retrieving revision 1.10
diff -u -p -r1.10 curl_multi_perform.3
--- docs/libcurl/curl_multi_perform.3 2 Sep 2009 14:57:05 -0000 1.10
+++ docs/libcurl/curl_multi_perform.3 31 Jan 2010 14:23:17 -0000
@@ -22,7 +22,8 @@ changed from the previous call (or is le
you've added to the multi handle), you know that there is one or more
transfers less "running". You can then call \fIcurl_multi_info_read(3)\fP to
get information about each individual completed transfer, and that returned
-info includes CURLcode and more.
+info includes CURLcode and more. If an added handle fails very quickly, it may
+never be counted as a running_handle.
When \fIrunning_handles\fP is set to zero (0) on the return of this function,
there is no longer any transfers in progress.
Index: lib/multi.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/multi.c,v
retrieving revision 1.210
diff -u -p -r1.210 multi.c
--- lib/multi.c 28 Jan 2010 15:34:18 -0000 1.210
+++ lib/multi.c 31 Jan 2010 14:23:17 -0000
@@ -1568,17 +1568,6 @@ static CURLMcode multi_runsingle(struct
multi->num_msgs++; /* increase message counter */
}
- if(CURLM_CALL_MULTI_PERFORM == result)
- /* Set the timeout for this handle to expire really soon so that it will
- be taken care of even when this handle is added in the midst of
- operation when only the curl_multi_socket() API is used. During that
- flow, only sockets that time-out or have actions will be dealt
- with. Since this handle has no action yet, we make sure it times out to
- get things to happen. Also, this makes it less important for callers of
- the curl_multi_* functions to bother about the CURLM_CALL_MULTI_PERFORM
- return code, as long as they deal with the timeouts properly. */
- Curl_expire(easy->easy_handle, 1);
-
return result;
}
@@ -1597,7 +1586,10 @@ CURLMcode curl_multi_perform(CURLM *mult
while(easy != &multi->easy) {
CURLMcode result;
- result = multi_runsingle(multi, easy);
+ do
+ result = multi_runsingle(multi, easy);
+ while (CURLM_CALL_MULTI_PERFORM == result);
+
if(result)
returncode = result;
@@ -1956,7 +1948,9 @@ static CURLMcode multi_socket(struct Cur
if(data->set.one_easy->easy_conn) /* set socket event bitmask */
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
- result = multi_runsingle(multi, data->set.one_easy);
+ do
+ result = multi_runsingle(multi, data->set.one_easy);
+ while (CURLM_CALL_MULTI_PERFORM == result);
if(data->set.one_easy->easy_conn)
data->set.one_easy->easy_conn->cselect_bits = 0;
@@ -1985,7 +1979,9 @@ static CURLMcode multi_socket(struct Cur
/* the first loop lap 'data' can be NULL */
if(data) {
- result = multi_runsingle(multi, data->set.one_easy);
+ do
+ result = multi_runsingle(multi, data->set.one_easy);
+ while (CURLM_CALL_MULTI_PERFORM == result);
if(CURLM_OK >= result)
/* get the socket(s) and check if the state has been changed since
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html