I am using libcurl with the multi interface (and libev) to receive data via http. Received data will be written to a relatively slow flash memory. curl_easy_pause() is used for flow control.
I noticed stuck transfers when the transfer is paused on the last invocation on the write callback, i.e. when the last chunk (in a non-http sense) of data is received. Once the transfer is resumed, it does not complete, although all data was received.
I observed the problem both when using curl_easy_pause(easy, CURLPAUSE_ALL) (consuming the data) from within the callback and as well when returning CURL_WRITEFUNC_PAUSE from the callback (without consuming the data).
Restarting the transfer will deliver the remaining data, in case it was not consumed (by returning CURL_WRITEFUNC_PAUSE). But in any case the transfer is not completed, that is CURLMSG_DONE is not received. It looks it will eventually be delivered, likely once the server closes the connection.
The application is single-threaded.
I will submit a example to demonstrate the problem, based on the evhiperfifo.c example, modified to pause the transfer on the first invocation and restart it after one second.
Fetching a resource with a short body (single callback invocation) will demonstrate the problem, e.g. http://google.com.
I expected the following
The transfer shall complete once all data was received. CURLMSG_DONE should be delivered by curl_multi_info_read().
... so that timeouts or other state machine actions get going again
after a changing pause state. For example, if the last delivery was
paused there's no pending socket activity.
Reported-by: sstruchtrup on github