Home  >  Article  >  Backend Development  >  A "Bug" in PHPCurl's millisecond timeout_PHP Tutorial

A "Bug" in PHPCurl's millisecond timeout_PHP Tutorial

WBOY
WBOYOriginal
2016-07-13 10:38:58887browse

Recently, our service is upgrading the libcurl used by PHP. We hope that the new version of libcurl will support millisecond timeouts, so that we can more precisely control the backend interface timeout, thereby improving the overall response time.

However, we found that on our CentOS server, when you set a timeout less than 1000ms, curl will not initiate any requests, but directly return a timeout error (Timeout reached 28).

It turns out that there is a pitfall here. CURL defaults to a Linux system. If the system standard DNS resolution is used, SIGALARM will be used to provide the function of controlling the domain name resolution timeout. However, SIGALARM does not support a timeout of less than 1s, so in 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
  • /* 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 is less than 1000ms, name resolution will directly return CURLRESOLV_TIMEOUT, which will eventually lead to CURLE_OPERATION_TIMEDOUT, and then Error, Timeout reached...

Isn't this... too cheating? Can't we use millisecond timeout? Then why do you provide this function?

Let’s look at the code again, the same 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
  • /* 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... So what is this thing?

This is easy, grep the code and find:


  • 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, it turns out to be this guy:


  • curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
  • ?>

After adding this OPT, everything is finally normal!

Postscript:

In this way, there will be a hidden danger, that is, DNS resolution will not be subject to timeout restrictions. This is generally not a problem within the company, but if the DNS server hangs, it may cause application timeout.

So is there any other way?

Yes, as Mike reminded us, we can let libcurl use c-ares (C library for asynchronous DNS requests) for name resolution. The specific details can be found when config curl:


  • ./configure --enable-ares[=PATH]

This way you don’t need to set NOSIGNAL A Bug in PHPCurls millisecond timeout_PHP Tutorial

PS, why is it called "Bug"? I'm just curious, why don't they use setitimer?

Reference: http://stackoverflow.com/questions/7987584/curl-timeout-less-than-1000ms-always-fails
Author: Laruence
URL of this article: http://www.laruence.com/2014/01/21/2939.html

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/735044.htmlTechArticleRecently, our service is upgrading the libcurl used by PHP. We expect that the new version of libcurl will support millisecond timeouts, so that we can More granular control over backend interface timeouts to improve overall response...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn