-
Notifications
You must be signed in to change notification settings - Fork 495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check if system has support for sub-second connect timeouts (CURL_VERSION_ASYNCHDNS) #264
Comments
Interesting, this constant must be new. I'm happy with allowing sub-second timeouts if ASYNCDNS is available.
When I dug into the underlying code, it appeared that if any DNS resolution was attempted, cURL would wait at least one tick (i.e. 1s) before failing.
Potentially not, but that's such an edge case I didn't think it was worth accounting for. |
@rmccue - I switched to building So this might introduce new bugs.
|
Gnarly. Seems like cURL internally is probably doing something strange with these timeouts. For a nice round number, 10ms could be a good minimum? |
As a soft minimum, 10 makes sense for the majority of use cases. Maybe add an option |
If you really want a specific timeout, you can use the |
This is the patch I'm using, but it's specific to php7.1 and a newer libcurl version (and certain libcurl build flags) --- a/library/Requests/Transport/cURL.php
+++ b/library/Requests/Transport/cURL.php
@@ -357,12 +360,28 @@ class Requests_Transport_cURL implements Requests_Transport {
// end, so we need to round up regardless of the supplied timeout.
//
// https://github.com/curl/curl/blob/4f45240bc84a9aa648c8f7243be7b79e9f9323a5/lib/hostip.c#L606-L609
- $timeout = max($options['timeout'], 1);
+ //
+ // NOTE: optimization for ['blocking' => false]
+ // use if you have a fast DNS resolver or frequently use IP addresses instead of dns
+ // TODO: I'm not sure if this is a generic fix - What about DNS lookups in HTTP Redirects?
+ $timeout = $options['timeout'];
if (is_int($timeout) || $this->version < self::CURL_7_16_2) {
curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout));
}
else {
+ // Make curl timeout work for sub-second values
+ // See https://github.com/rmccue/Requests/issues/264
+ // and http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=CURLOPT_NOSIGNAL&sect=3
+ curl_setopt($this->handle, CURLOPT_NOSIGNAL, 1);
+ // check to support for upgraded curl and/or threaded async resolver.
+ // (1 millisecond seems to be treated as a special value, and it ended up taking longer than 2 milliseconds)
+ if ($timeout > 0) {
+ $timeout = max($timeout, 0.002);
+ }
curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000));
}
@@ -370,6 +389,12 @@ class Requests_Transport_cURL implements Requests_Transport {
curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout']));
}
else {
+ // Make curl timeout work for sub-second values
+ // See https://github.com/rmccue/Requests/issues/264
+ // and http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=CURLOPT_NOSIGNAL&sect=3
+ curl_setopt($this->handle, CURLOPT_NOSIGNAL, 1);
curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000));
} |
Related to 4e1c18f. I ask for this because I want to have a 'timeout' of less than a second.
It seems like it should be possible to avoid using signals such as alarm() (via CURLOPT_NOSIGNAL), and to detect if there is an alternative dns resolver (via CURL_VERSION_ASYNCHDNS)
https://curl.haxx.se/libcurl/c/curl_version_info.html
http://stackoverflow.com/questions/25998063/how-can-i-tell-if-the-libcurl-installed-has-asynchronous-dns-enabled also mentions this.
Also, a workaround (when ASYNCDNS is absent) might be to disable timeouts for dns lookup (if the 'connect' time is sub-millisecond), so that the request timeout can be set to less than one second. I'm not sure if that will introduce new bugs, e.g. if DNS is slow/unreliable.
http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=CURLOPT_NOSIGNAL&sect=3
On an unrelated note, is the minimum necessary if the host name is an IPV4 or IPV6 address (e.g. 127.0.0.1, etc.), and HTTP redirects are disabled? (may have to set CURLOPT_NOSIGNAL so that the "lookup" will still avoid timing out)
The text was updated successfully, but these errors were encountered: