aboutsummaryrefslogtreecommitdiff
path: root/CHANGES
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2010-02-01 21:42:44 +0000
committerDaniel Stenberg <daniel@haxx.se>2010-02-01 21:42:44 +0000
commit55f1e787f34cd3d86aa3d6bf981f077de86be265 (patch)
treea1c1dcbf05a0e54af3cbeec6da49c39d6542c87e /CHANGES
parent516cf5c8ddd6a094babdf4ee2d3b2fa4c7a48b0e (diff)
We introduce a loop in lib/multi.c around all calls to multi_runsingle() and
simply check for CURLM_CALL_MULTI_PERFORM internally. This has the added benefit that this goes in line with my long-term wishes to get rid of the CURLM_CALL_MULTI_PERFORM all together from the public API.
Diffstat (limited to 'CHANGES')
-rw-r--r--CHANGES57
1 files changed, 57 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index cd4634e8f..b5a512a78 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,63 @@
Changelog
+Daniel Stenberg (1 Feb 2010)
+- Using the multi_socket API, it turns out at times it seemed to "forget"
+ connections (which caused a hang). It turned out to be an existing (7.19.7)
+ bug in libcurl (that's been around for a long time) and it happened like
+ this:
+
+ The app calls curl_multi_add_handle() to add a new easy handle, libcurl will
+ then set it to timeout in 1 millisecond so libcurl will tell the app about
+ it.
+
+ The app's timeout fires off that there's a timeout, the app calls libcurl as
+ we so often document it:
+
+ do {
+ res = curl_multi_socket_action(... TIMEOUT ...);
+ } while(CURLM_CALL_MULTI_PERFORM == res);
+
+ And this is the problem number one:
+
+ When curl_multi_socket_action() is called with no specific handle, but only
+ a timeout-action, it will *only* perform actions within libcurl that are
+ marked to run at this time. In this case, the request would go from INIT to
+ CONNECT and return CURLM_CALL_MULTI_PERFORM. When the app then calls libcurl
+ again, there's no timer set for this handle so it remains in the CONNECT
+ state. The CONNECT state is a transitional state in libcurl so it reports no
+ sockets there, and thus libcurl never tells the app anything more about that
+ easy handle/connection.
+
+ libcurl _does_ set a 1ms timeout for the handle at the end of
+ multi_runsingle() if it returns CURLM_CALL_MULTI_PERFORM, but since the loop
+ is instant the new job is not ready to run at that point (and there's no
+ code that makes libcurl call the app to update the timout for this new
+ timeout). It will simply rely on that some other timeout will trigger later
+ on or that something else will update the timeout callback. This makes the
+ bug fairly hard to repeat.
+
+ The fix made to adress this issue:
+
+ We introduce a loop in lib/multi.c around all calls to multi_runsingle() and
+ simply check for CURLM_CALL_MULTI_PERFORM internally. This has the added
+ benefit that this goes in line with my long-term wishes to get rid of the
+ CURLM_CALL_MULTI_PERFORM all together from the public API.
+
+ The downside of this fix, is that the counter we return in 'running_handles'
+ in several of our public functions then gets a slightly new and possibly
+ confusing behavior during times:
+
+ If an app adds a handle that fails to connect (very quickly) it may just
+ as well never appear as a 'running_handle' with this fix. Previously it
+ would first bump the counter only to get it decreased again at next call.
+ Even I have used that change in handle counter to signal "end of a
+ transfer". The only *good* way to find the end of a individual transfer
+ is calling curl_multi_info_read() to see if it returns one.
+
+ Of course, if the app previously did the looping before it checked the
+ counter, it really shouldn't be any new effect.
+
Yang Tse (26 Jan 2010)
- Constantine Sapuntzakis' and Joshua Kwan's work done in the last four months
relative to the asynchronous DNS lookups, along with with some integration