cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: libcurl + libevent2: Stalling if no data is received/written [new timeout patch]

From: Dirk Manske <dm_at_nonitor.de>
Date: Mon, 30 Aug 2010 00:09:36 +0200

On Sunday 29 August 2010 00:15:41 Daniel Stenberg wrote:
> On Wed, 25 Aug 2010, Dirk Manske wrote:
>
> > My patch fixes that. But indeed it's a bad patch. The operation timeout
> > should be set only one time. But I'm not sure where the correct place is.
>
> I found something interesting: we only ever call expire(0) from within
> hostthre.c to kill a single timeout, the other three times we use the zero
> argument we truly want to remove all existing timeouts.
Nothing new to me... as already said, those expire 0 are harmless.

> I just tried the multi-single example program with CURLOPT_TIMEOUT set against
> a very slow URL, and it works as assumed with this simple patch applied. I'm
> convinced this patch is correct no matter what, so I will commit and push this
> in a second:

Sorry, that fixes nothing. The timeouts with multi-single had worked
before already. Because it's really polling not event driven.

> + if(data->set.timeout)
> + Curl_expire(data, data->set.timeout);
> +
> + if(data->set.connecttimeout)
> + Curl_expire(data, data->set.connecttimeout);
> +
The second expire also overwrites the first one (if connecttimeout<timeout).

e.g. with
    curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, 10 );
    curl_easy_setopt(http_handle, CURLOPT_CONNECTTIMEOUT, 5 );
...
    while( still_running ) {
...
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        curl_multi_timeout( multi_handle, &curl_timeo );
        printf( "curl to: %ld\n", curl_timeo ); /// added that one
        if( curl_timeo >= 0 ) {
            timeout.tv_sec = curl_timeo / 1000;
            if( timeout.tv_sec > 1 )
                timeout.tv_sec = 1;
            else
                timeout.tv_usec = (curl_timeo % 1000) * 1000;
        }
        curl_multi_fdset( multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd );
        rc = select( maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout );
...
           while( CURLM_CALL_MULTI_PERFORM == curl_multi_perform( multi_handle, &still_running ) );
...
    }

you will get

STATE: WAITPERFORM => PERFORM handle 0xc19318; (connection #0)
curl to: 4997
curl to: 3996
curl to: 2995
curl to: 1994
curl to: -1
curl to: -1
curl to: -1
curl to: -1
curl to: -1
* Operation timed out after 10004 milliseconds with 0 bytes received

You see that the 10 operation timeout was overwritten bei the 5s connect
timeout. But the example still work's because it forces a 1s timeout
on select. The operation timeout will be detected by curl_multi_perform(...)

If you use the timer callback as in hiperfifo you will only get the connect
timeout. The timer callback get called one time after ~5s but not more again.

dm

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2010-08-30