cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Questions about timeout during transfer

From: Saqib Ali <saqib.ali.75_at_gmail.com>
Date: Thu, 26 May 2011 01:47:30 -0400

You certainly are not the only one, that's why libcurl provides these
> options:
>
> http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTLOWSPEEDLIMIT
> http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTLOWSPEEDTIME
>
> - Jeff
>

Thanks Jeff! This was very helpful.

The Low-Speed timeout works pretty well for me.
However, I ran some tests that raise questions in my mind about certain
delays that I'm noticing..

I set my low-speed limit to 1 byte/sec. And I set the low-speed time to 1
second.
I start a transfer. During the transfer I break the connection between the
two machines. Below I have included the output of the test (with some minor
annotations in < >) and the source-code of my test program.

Even though I set the low-speed-time to 60 seconds, It waits 68 seconds
before timing out.
After it times out, disconnecting and closing the connection takes a
whopping 62 additional seconds. Why is there an 8-second delay on my timer.
And why does it take 62 seconds to disconnect? Is that normal?

- Saqib

Standard Output:
=============
% myProg
Enter File Name: myFile.dat
* About to connect() to myIPAddr port 22 (#0)
* Trying myIPAddr... * 0x67e18 is at send pipe head!
* STATE: CONNECT => WAITCONNECT handle 0x49c78; (connection #0)
* Connected to myIPAddr (myIPAddr) port 22 (#0)
* SFTP 0x70b38 state change from SSH_STOP to SSH_S_STARTUP
* SFTP 0x70b38 state change from SSH_S_STARTUP to SSH_HOSTKEY
* SFTP 0x70b38 state change from SSH_HOSTKEY to SSH_AUTHLIST
* STATE: WAITCONNECT => PROTOCONNECT handle 0x49c78; (connection #0)
* SSH authentication methods available:
gssapi-keyex,gssapi-with-mic,publickey,password,keyboard-interactive
* SFTP 0x70b38 state change from SSH_AUTHLIST to SSH_AUTH_PKEY_INIT
* Using ssh public key file /myHomeDir/.ssh/id_dsa.pub
* Using ssh private key file /myHomeDir/.ssh/id_dsa
* SFTP 0x70b38 state change from SSH_AUTH_PKEY_INIT to SSH_AUTH_PKEY
* SSH public key authentication failed: Unable to open public key file
* SFTP 0x70b38 state change from SSH_AUTH_PKEY to SSH_AUTH_PASS_INIT
* SFTP 0x70b38 state change from SSH_AUTH_PASS_INIT to SSH_AUTH_PASS
* Initialized password authentication
* SFTP 0x70b38 state change from SSH_AUTH_PASS to SSH_AUTH_DONE
* Authentication complete
* SFTP 0x70b38 state change from SSH_AUTH_DONE to SSH_SFTP_INIT
* SFTP 0x70b38 state change from SSH_SFTP_INIT to SSH_SFTP_REALPATH
* SSH CONNECT phase done
* SFTP 0x70b38 state change from SSH_SFTP_REALPATH to SSH_STOP
* STATE: PROTOCONNECT => DO handle 0x49c78; (connection #0)
* DO phase starts
* SFTP 0x70b38 state change from SSH_STOP to SSH_SFTP_QUOTE_INIT
* SFTP 0x70b38 state change from SSH_SFTP_QUOTE_INIT to SSH_SFTP_TRANS_INIT
* SFTP 0x70b38 state change from SSH_SFTP_TRANS_INIT to SSH_SFTP_UPLOAD_INIT
* STATE: DO => DOING handle 0x49c78; (connection #0)
* SFTP 0x70b38 state change from SSH_SFTP_UPLOAD_INIT to SSH_STOP
* DO phase is complete
* STATE: DOING => DO_DONE handle 0x49c78; (connection #0)
11 | 0% transferred.
* STATE: DO_DONE => WAITPERFORM handle 0x49c78; (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x49c78; (connection #0)
* Expire cleared
Elapsed Time: 11 seconds | 3.11223% transferred.
Elapsed Time: 12 seconds | 6.22445% transferred.
Elapsed Time: 12 seconds | 9.33668% transferred.
Elapsed Time: 12 seconds | 12.4489% transferred.
Elapsed Time: 12 seconds | 15.5611% transferred.
Elapsed Time: 13 seconds | 18.6734% transferred.
Elapsed Time: 13 seconds | 21.7856% transferred.
Elapsed Time: 13 seconds | 24.8978% transferred.
Elapsed Time: 14 seconds | 28.01% transferred.
Elapsed Time: 14 seconds | 31.1223% transferred.
Elapsed Time: 14 seconds | 34.2345% transferred.
Elapsed Time: 15 seconds | 37.3467% transferred.
Elapsed Time: 15 seconds | 40.4589% transferred.
Elapsed Time: 15 seconds | 43.5712% transferred.
Elapsed Time: 16 seconds | 46.6834% transferred.
Elapsed Time: 16 seconds | 49.7956% transferred.
Elapsed Time: 16 seconds | 52.9078% transferred.
Elapsed Time: 17 seconds | 56.0201% transferred.
Elapsed Time: 17 seconds | 59.1323% transferred.
Elapsed Time: 17 seconds | 62.2445% transferred.
Elapsed Time: 18 seconds | 65.3567% transferred.
Elapsed Time: 18 seconds | 68.469% transferred.
Elapsed Time: 19 seconds | 71.5812% transferred.
Elapsed Time: 19 seconds | 74.6934% transferred.
Elapsed Time: 19 seconds | 77.8056% transferred.
Elapsed Time: 20 seconds | 80.9179% transferred.
Elapsed Time: 20 seconds | 84.0301% transferred.

<Annotation: The connection is broken at this point....Wait of 68
seconds...>

* Operation too slow. Less than 1 bytes/sec transfered the last 60 seconds
* SSH DISCONNECT starts now
* SFTP 0x70b38 state change from SSH_STOP to SSH_SFTP_SHUTDOWN

<Annotation: Wait of 62 seconds>

* Operation too slow. Less than 1 bytes/sec transfered the last 60 seconds
* SSH DISCONNECT is done
* Closing connection #0
Elapsed Time: 150 seconds | Xfer Stopped! stillRunning = 0
* Expire cleared
curl_multi_remove_handle() was successfull!

My Test Program So that you can reproduce:
==================================

#include "curl.h"
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>

using namespace std;

typedef int (*callBackP) (void *clientp, double dltotal, double dlnow,
double ultotal, double ulnow);
time_t startTime = time(0);

static int progressCallBack(void *argSrcFile, double dltotal, double dlnow,
double ultotal, double ulnow)
{

static double lastPrint;

if (ultotal > 0)
{
double currProg = (ulnow*100)/ultotal;
if ((currProg >= (lastPrint+3.0) || currProg >= 100))
{
lastPrint = currProg;
cout << "Elapsed Time: " << difftime(time(0), startTime) << "seconds | " <<
currProg << "% transferred." << endl;
}
if (currProg == 100)
{
lastPrint = -5.0;
return -1;
}
}
else
{
lastPrint = -5.0;
}
return 0;
}

int main()
{
CURLMcode retVal;

curl_global_init(CURL_GLOBAL_ALL);
CURLM* multiHandle = curl_multi_init();
CURL* newEasyHandle = curl_easy_init();

string fileName;
cout << "Enter File Name: ";
cin >> fileName;

string targetURL = "sftp://myIPAddr/~/" + fileName;

curl_easy_setopt(newEasyHandle, CURLOPT_UPLOAD, 1);
curl_easy_setopt(newEasyHandle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(newEasyHandle, CURLOPT_CONNECTTIMEOUT, 60);
curl_easy_setopt(newEasyHandle, CURLOPT_LOW_SPEED_LIMIT, 1);
curl_easy_setopt(newEasyHandle, CURLOPT_LOW_SPEED_TIME, 60);

    // Setup The Callback function
callBackP currCallBack = progressCallBack;
    curl_easy_setopt(newEasyHandle, CURLOPT_NOPROGRESS, 0);
    curl_easy_setopt(newEasyHandle, CURLOPT_PROGRESSFUNCTION,
progressCallBack );
    curl_easy_setopt(newEasyHandle, CURLOPT_PROGRESSDATA, (void*)NULL);

FILE* fd = fopen(fileName.c_str(), "r"); // open file to upload
curl_easy_setopt(newEasyHandle, CURLOPT_READDATA, fd);
curl_easy_setopt(newEasyHandle, CURLOPT_USERPWD, "myUserName:myPassword");
curl_easy_setopt(newEasyHandle, CURLOPT_URL, targetURL.c_str());
struct stat fileInfo;
stat(fileName.c_str(), &fileInfo);
curl_easy_setopt(newEasyHandle, CURLOPT_INFILESIZE, (long)fileInfo.st_size);

// BLOCK A: Now add the easyHandle to the multiStack
curl_multi_add_handle(multiHandle, newEasyHandle);
int stillRunning, retValcm;
retVal = curl_multi_perform(multiHandle, &stillRunning);
if (retVal != CURLM_OK)
cout << "curl_multi_perform() failed!" << endl;
// END BLOCK A

// BLOCK B: Wait until the transfers are done.
while (stillRunning > 0)
{
retValcm = curl_multi_perform(multiHandle, &stillRunning);
}
// END BLOCK B
cout << "Elapsed Time: " << difftime(time(0), startTime) << "seconds | " <<
"Xfer Stopped! stillRunning = " << stillRunning << endl;

// BLOCK C: Now remove the easyHandle from the multiStack
sleep(2);
retVal = curl_multi_remove_handle(multiHandle, newEasyHandle);
if (retVal == CURLM_OK)
cout << "curl_multi_remove_handle() was successfull!" << endl;
else
cout << "curl_multi_remove_handle() failed!" << endl;
// END BLOCK C

return 0;

}

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2011-05-26