A "Bug" in milliseconds of PHPCurl timeout ". Recently, our service is upgrading the libcurl used by php. we expect the new version of libcurl to support millisecond-level timeout, so that we can more precisely control the backend interface timeout, in this way, the overall response is improved. our service is upgrading the libcurl used by php recently. we expect that the new version of libcurl supports millisecond-level timeout, so that we can control the backend interface timeout more precisely, this improves the overall response time.
However, we found that on our CentOS server, when you set a Timeout value less than Ms, curl will not initiate any request, but will directly return a Timeout error (Timeout reached 28 ).
Originally, there was a pitfall here. CURL is the default. in Linux, if the system standard DNS resolution is used, SIGALARM will be used to control domain name resolution timeout, however, SIGALARM does not support timeout of less than 1 S. Therefore, in the code of libcurl 7.28.1 (note the Chinese comment line ):
Int Curl_resolv_timeout (struct connectdata * conn,
- Const char * hostname,
- Int port,
- Struct Curl_dns_entry ** entry,
- Long timeoutms)
- {
- .......
- .......
- # Ifdef USE_ALARM_TIMEOUT
- If (data-> set. no_signal)
- /* Ignore the timeout when signals are disabled */
- Timeout = 0;
- Else
- Timeout = timeoutms;
-
- If (! Timeout)
- /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
- Return Curl_resolv (conn, hostname, port, entry );
-
- If (timeout <1000) // if it is less than 1000, the system returns a timeout value.
- /* The alarm () function only provides integer second resolution, so if
- We want to wait less than one second we must bail out already now .*/
- Return CURLRESOLV_TIMEDOUT;
-
- ....
- ....
-
It can be seen that when your Timeout time is less than Ms, name resolution will directly return CURLRESOLV_TIMEOUT, which will eventually lead to CURLE_OPERATION_TIMEDOUT, and then Error, Timeout reached...
This .... Is it too bad? Is it hard to say that we cannot Time Out in milliseconds? What do you do with this function?
Check the code or the code just now. pay attention to this (Chinese comment line ):
- # Ifdef USE_ALARM_TIMEOUT
- If (data-> set. no_signal) // pay attention to this line
- /* Ignore the timeout when signals are disabled */
- Timeout = 0;
- Else
- Timeout = timeoutms;
-
- If (! Timeout)
- /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
- Return Curl_resolv (conn, hostname, port, entry );
-
- If (timeout <1000)
- /* The alarm () function only provides integer second resolution, so if
- We want to wait less than one second we must bail out already now .*/
- Return CURLRESOLV_TIMEDOUT;
It seems that as long as set. no_signal is 1, it can be bypassed... What is this?
This is simple, grep the code, and found:
- Case CURLOPT_NOSIGNAL:
- /*
- * The application asks not to set any signal () or alarm () handlers,
- * Even when using a timeout.
- */
- Data-> set. no_signal = (0! = Va_arg (param, long ))? TRUE: FALSE;
- Break;
Haha:
-
- Curl_setopt ($ ch, CURLOPT_NOSIGNAL, 1 );
- ?>
After this OPT is added, everything is finally normal!
Postscript:
In this way, there will be a hidden risk, that is, DNS resolution will not be limited by timeout, which is because within the company, there is generally no problem, but in case of the DNS server hang, the application may time out.
Is there any other way?
Yes, that's what Mike reminds us. we can make libcurl use c-ares (C library for asynchronous DNS requests) for name resolution. The details can be found at config curl:
- ./Configure -- enable-ares [= PATH]
In this way, you do not need to set NOSIGNAL.
PS. why do I just wonder why they don't need setimer?
Reference: http://stackoverflow.com/questions/7987584/curl-timeout-less-than-1000ms-always-fails
Author: Laruence
Address: http://www.laruence.com/2014/01/21/2939.html
Wait, expect the new version of libcurl to support millisecond-level timeout, so as to more precisely control the backend interface timeout, thus improving the overall response...