curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Re: curl_multi_timeout and the multi_socket API

From: Henrik Holst via curl-library <curl-library_at_cool.haxx.se>
Date: Mon, 5 Apr 2021 16:54:00 +0200

Den sön 4 apr. 2021 kl 12:28 skrev Daniel Stenberg <daniel_at_haxx.se>:

> On Sat, 3 Apr 2021, Henrik Holst wrote:
>
> (Let me just add some meat to this and explain this described behavior.)
>
> > As I wrote earlier, usually when you call curl_multi_add_handle(), the
> Timer
> > Function CB is called once by curl with timeout set to 0. Then when you
> call
> > curl_multi_socket_action() with CURL_SOCKET_TIMEOUT the Timer Function
> CB is
> > usually called once more but this time with a timeout set to 1.
>
> This description matches how libcurl *did* behave. More recent versions
> don't
> need to poll the name resolve results from the threaded resolver so the
> timeout pattern will be slightly different.
>

On a side note (and perhaps I should have written this in a separate mail)
I did notice that the timer function callback returns far too low values
for long polling http servers if the user haven't set CURLOPT_TIMEOUT.
Caveat here is that I have only tested this with 7.58 and 7.68 as of yet
and not with HEAD.

So one of the external services that I connect to uses long polling to
avoid having people like me polling the service several times per second in
order to get the latest update with minimal latency. Normally I set
CURLOPT_TIMEOUT for all connections, but yesterday I experimented by using
TCP Keep-alive instead so I commented out the setting of CURLOPT_TIMEOUT
and noticed that the application took 100% cpu, later examination revealed
that this was because the last timeout from the Timer Function callback was
1 (and sometimes 0).

Here is one such run with CURLOPT_VERBOSE set, unfortunately the server is
not public so replication might be hard:

For this I simply print out the given timeout with this callback:

static int CURL_timer_callback (__attribute__((unused)) CURLM *multi, long
timeout, void *userp)
{
   printf ("timeout: %ld\n", timeout);
   return 0;
}

timeout: -1
timeout: 0
timeout: 1
timeout: 1
timeout: 1
timeout: 4
timeout: 7
timeout: 1
timeout: 15
timeout: 1
timeout: 31
timeout: 1
* Trying xxx.170.239.163:80...
* TCP_NODELAY set
timeout: 49
* Connected to press.xxx.com (xxx.170.239.163) port 80 (#0)
> GET /items&lastId=126599 HTTP/1.1
Host: press.xxx.com
Accept: */*

timeout: 119
timeout: 1
^C* Closing connection 0

As you can see the last timeout given here was 1 and then about 10s later I
hit ctrl-c to quit. I was rather expecting it to be -1 since the default
timeout should be infinite.

If I however set CURLOPT_TIMEOUT to say 1800L then:
timeout: -1
timeout: 0
timeout: 1
timeout: 2
timeout: 3
timeout: 1
timeout: 8
timeout: 15
timeout: 1
timeout: 31
* Trying xxx.170.239.163:80...
* TCP_NODELAY set
timeout: 10
timeout: 1
timeout: 188
* Connected to press.xxx.com (xxx.170.239.163) port 80 (#0)
> GET /items&lastId=126599 HTTP/1.1
Host: press.xxx.com
Accept: */*

timeout: 1799747
^C* Closing connection 0

Here the timeout it set to the configured value of ~1800000ms

/HH


-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.se/mail/etiquette.html
Received on 2021-04-05