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

A 'Bug' in PHPCurl's millisecond timeout_PHP Tutorial

WBOY
Release: 2016-07-13 10:38:58
Original
950 people have browsed it

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):

Copy after login
Copy after login
Copy after login
Copy after login
  • #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... So what is this thing?

This is easy, grep the code and find:

Copy after login
Copy after login
Copy after login
Copy after login
  • 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:

Copy after login
Copy after login
Copy after login
Copy after login
  • 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:

Copy after login
Copy after login
Copy after login
Copy after login
  • ./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...
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template