cURL / Mailing Lists / curl-library / Single Mail

curl-library

And speaking of data sending bugs...

From: Nick Zitzmann <nick_at_chronosnet.com>
Date: Mon, 11 Feb 2013 15:00:35 -0700

Hi:

While I was testing the patch I made over the weekend for the curl_darwinssl transmission bug, I found a related issue that I suspect affects all builds of 7.29.0: If a program creates a curl_easy handle, sets CURLOPT_TIMEOUT to some value greater than 0 but less than the amount of time it takes to transfer a file, and then issues an HTTP command that sends data to the server (e.g. PUT, POST, PROPFIND, REPORT, extended MKCOL, etc.), then after the amount of seconds entered in CURLOPT_TIMEOUT elapses and the transfer is not done yet, libcurl reports "Operation timed out after X milliseconds with 0 out of -1 bytes received" where X is the timeout value in milliseconds.

Steps to reproduce:

1. Create a curl_easy handle
2. Set CURLOPT_URL to a URL on a Web server where you have PUT permission (I tested using HTTPS, but this should happen over HTTP as well)
3. Set CURLOPT_UPLOAD to 1L
4. Set CURLOPT_READDATA to a FILE that would take more than 30 seconds to upload on your network connection
5. Set CURLOPT_INFILESIZE_LARGE to the file size (I didn't try using chunked encoding)
6. Set CURLOPT_TIMEOUT to 30L
7. Set CURLOPT_HTTPAUTH to CURLAUTH_ANY
8. Set CURLOPT_USERNAME and CURLOPT_PASSWORD to your user name and password for the server
9. Call curl_easy_perform()

One would expect the file to be uploaded to the URL, but instead libcurl (not the server) times out before all data is transferred and aborts the transfer, returning the error message "Operation timed out after 60000 milliseconds with 0 out of -1 bytes received". The problem does not happen if timeout is set to an arbitrary really large number.

Looking into this a little deeper, it appears that the handle's state changes from CURLM_STATE_DO after the headers are sent to CURLM_STATE_PERFORM. Once the user is authenticated and the server replies with HTTP/1.1 100 Continue, libcurl starts sending the file data, but it doesn't look like there's any other state change at this point. Perhaps the solution here is to break CURLM_STATE_PERFORM into send and receive states, not time out during the send state, and change from send to receive after sending is done? I don't know if I'd break something if I did this myself, so I'm wondering if an expert could look into this…

Nick Zitzmann
<http://www.chronosnet.com/>

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2013-02-11