cURL / Mailing Lists / curl-library / Single Mail

curl-library

not receiving CURLMSG_DONE or other end-of-transfer signals

From: Daniel Hardman <daniel.hardman_at_gmail.com>
Date: Mon, 20 Apr 2015 18:01:03 -0600

I have some code that is based on asiohiper.cpp (so, event-oriented multi
with asio). I have refactored it, and in doing so, it seems that I've
introduced a bug. I've been debugging for multiple days now, and my brain
is aching enough that I am hoping someone can suggest some new ideas for me
based on the symptoms I describe. (Reference env: ubuntu 14.04 x64, curl
7.35). I will of course continue debugging on my own, and if I'm still
stuck tomorrow I may post a follow-up message with sample code, but right
now I'm just looking for 30 seconds of general wisdom plus some
clarification about expected behavior. (See Q1 thru Q3 below).

At this point I have a very simple program flow. All I want to do is
download http://www.google.com/. I initialize a CURLM and a CURL easy
handle. I configure each in the same way that asiohiper.cpp shows. I have
verbose turned on. When I call curl_multi_add_handle(), the whole download
begins, and everything looks fine. DNS works; Google responds with a bunch
of headers, including Transfer-Encoding: Chunked. The callback that accepts
data (body of the response) fires 2 or 3 times; the final time I see it
firing it usually gives me exactly 16384 bytes. (Google's overall response
size seems to be about 3 or 4 times as big as CURL_MAX_WRITE_SIZE.)

What's puzzling is that the whole process just hangs at that point. libcurl
never calls me back with the final bytes of the response. I ran tcpdump and
observed that google's response arrives immediately with a correct final
0-byte chunk, despite the hang in my app--but I never get a final callback
telling me that the socket is readable again, or that additional data has
been received. My progress function never tells me anything is done. I
never get a CURLMSG_DONE. It's as if my easy handle is no longer being
monitored by epoll, or some code is losing track of a socket's current
status. I am returning the number of bytes processed (==number of bytes
received) from my CURLOPT_WRITEFUNCTION callback, so that's not stopping
the transfer...

One possible cause is that I've broken my timer adjustment callback
(CURLMOPT_TIMERFUNCTION) in some way. I've compared mine to the original
sample, and I don't see anything useful. Tracing suggests that all sockets
are still registered, all FDs are still open, etc. However, as I read the
docs, I began to wonder:

***Q1: If the callback identified by CURLMOPT_TIMERFUNCTION is called with
timeout_ms == 0, the docs say to call curl_multi_socket_action() asap. I'm
doing that. Do I *also* need to reschedule the timer, or should the
existing timer be deleted? (I'm assuming the latter, but I've tried both
ways without changing the outcome of my experiment.)

***Q2: I found some discussion on StackOverflow about whether CURLMSG_DONE
could be relied upon (e.g., http://stackoverflow.com/a/10486468). If
transfers end in unusual ways (e.g., remote web server prematurely closes
socket), is the intended behavior supposed to be that 100% of the time,
transfers conclude with a CURLMSG_DONE -- or is there some other way to
reliably detect completion?

***Q3: Do any of you experts recognize the symptoms I've described? What
hints can you suggest about places to look or experiments to prove/disprove
theories?

--Daniel Hardman

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2015-04-21