Re: Bug in curl multi DONE->COMPLETED state transition?
Date: Sat, 2 Aug 2008 22:37:15 +0200 (CEST)
On Sat, 2 Aug 2008, Albert Lee wrote:
> ???I think I've finally pinpointed the cause of the issue.
Very nice piece of research and bug tracking, obviously!
> If the handle is in one of several states at the time including
> ??????CURLM_STATE_DONE, ???singlesocket()'s multi_getsock() call will not
> populate the socket array that the handle's sockets are checked against.
> multi_socket() calls ???multi_runsingle() on the specified handle and if
> the handle is in CURLM_STATE_PERFORM it will transition to
> CURLM_STATE_DONE, but ??????multi_runsingle() needs to be called again to
> reach CURLM_STATE_COMPLETED. Reaching ???CURLM_STATE_COMPLETED will also
> call ???Curl_done() and because we are not reusing sockets they will be
> However, singlesocket() is immediately called after ???multi_runsingle(). If
> the handle state was just changed to CURLM_STATE_DONE, singlesocket()
> discards the sockets as described above - and since Curl_done() has not yet
> been called the cleanup for those sockets never happens.
But isn't this libcurl function then returning CURLM_CALL_MULTI_PERFORM (which
your program should react on)?
And further, hasn't it already set a timeout at the end of multi_runsingle()
that expires after 1 millisecond that also would cause curl_multi_socket*() to
get called on that particular file descriptor?
I think the key to this problem is to understand why your app isn't calling
libcurl again so that it drives the state forward to COMPLETED instead of
letting it stay in DONE. Or if it indeed does call it, why that isn't enough.
> Making ???singlesocket() not modify the socket hash table if the handle is
> in ??????CURLM_STATE_DONE seems to fix the problem - the sockets can be
> removed in a subsequent multi_socket() called at which point the handle will
> be in CURLM_STATE_COMPLETED and the sockets will actually have been closed.
That seems like a band-aid fix that is not very nice. singlesocket() should be
state-agnostic and there should never be a reason to just "skip" a state. If
the DONE state would need a special set of sockets then those sockets should
be set in the array by the multi_getsock() function IMO.
-- / daniel.haxx.seReceived on 2008-08-02