libcurl often fails to call our timer_callback function to set up the
next timer when it should. The can mean that a download hangs, for
example when it's waiting for getaddrinfo() to complete in a thread it
spawned for that purpose.

Don't ever allow the timer to be unset while there are downloads in
progress; use curl_multi_timeout() to check for the next timeout, and if
curl returns -1 to indicate that there's no timer pending, then set it
anyway for half a second.
---
This version of the patch to PacRunner's cURL module is revised to cope
with a hypothetical future version of libcurl with this bug fixed, by
only doing this dance when the timeout isn't already set.

Copied to cURL list for a sanity check.

 plugins/curl.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/plugins/curl.c b/plugins/curl.c
index 41c4e2c..0214ed2 100644
--- a/plugins/curl.c
+++ b/plugins/curl.c
@@ -192,6 +192,7 @@ static int socket_callback(CURL *easy, curl_socket_t 
sockfd, int what,
        return 0;
 }
 
+static int timer_callback(CURLM *multi, long timeout_ms, void *user_data);
 static gboolean timeout_callback(gpointer user_data)
 {
        CURLM *multi = user_data;
@@ -209,6 +210,26 @@ static gboolean timeout_callback(gpointer user_data)
 
        check_sockets(multi, result, handles);
 
+       /* Sometimes, curl doesn't set a new timeout when it should. */
+       if (handles && !timeout_source) {
+               long next_timer = -1;
+
+               curl_multi_timeout(multi, &next_timer);
+
+               /* From the curl_multi_timeout() man page:
+                  Note: if libcurl returns a -1 timeout here, it just means
+                  that libcurl currently has no stored timeout value. You
+                  must not wait too long (more than a few seconds perhaps)
+                  before you call curl_multi_perform() again.
+
+                  With curl < 7.21.2 it's very true; we'll never poll for
+                  completion of the asynchronous DNS lookup otherwise.
+               */
+               if (next_timer == -1)
+                       next_timer = 500;
+
+               timer_callback(multi, next_timer, NULL);
+       }
        return FALSE;
 }
 
-- 
1.7.3.2



-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to