curl timeout problem and solution

If you want cURL to timeout in less than one second, you can use CURLOPT_TIMEOUT_MS, although there is a bug/”feature”  on “Unix-like systems” that causes libcurl to timeout immediately if the value is < 1000 ms with the error “cURL Error (28): Timeout was reached”.  The explanation for this behavior is:

“If libcurl is built to use the standard system name resolver, that portion of the transfer will still use full-second resolution for timeouts with a minimum timeout allowed of one second.”

What this means to PHP developers is “You can use this function without testing it first, because you can’t tell if libcurl is using the standard system name resolver (but you can be pretty sure it is)”

The problem is that on (Li|U)nix, when libcurl uses the standard name resolver, a SIGALRM is raised during name resolution which libcurl thinks is the timeout alarm.

The solution is to disable signals using CURLOPT_NOSIGNAL.  Here’s an example script that requests itself causing a 10-second delay so you can test timeouts:

<?php
if (!isset($_GET['foo'])) {
// Client
$ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
$data = curl_exec($ch);
$curl_errno = curl_errno($ch);
$curl_error = curl_error($ch);
curl_close($ch);

if ($curl_errno > 0) {
echo “cURL Error ($curl_errno): $curl_error\n”;
} else {
echo “Data received: $data\n”;
}
} else {
// Server
sleep(10);
echo “Done.”;
}
?>

About these ads

9 thoughts on “curl timeout problem and solution

  1. I tried this solution to the problem and it doesn’t work for me. Heres my code. Any ideas?

    $ch = curl_init($url); // set handle of curl session to ch
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 50);
    curl_exec($ch);
    curl_close($ch);

      • It’s the strangest thing, I know I can do an update to a newer version of curl that should fix the problem but the server has so many program updates its behind on it won’t let me install a newer version. 

        But my problem is just like you said, anything under 1000  ms times out too early, but when I add “no signal” it doesn’t work either. It still goes to 1000ms. It’s the weirdest thing

  2. HI Ravi,
    I faced a core dump in curl_easy_perform() when i used the CURLOPT_TIMEOUT option but i didn’t use the CURLOPT_NOSIGNAL option . Is CURLOPT_NOSIGNAL the reason behind it?????
    will CURLOPT_NOSIGNAL solve the core dump ??????

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s