php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76480 Use curl_multi_wait() so that timeouts are respected
Submitted: 2018-06-15 07:03 UTC Modified: 2018-10-12 15:20 UTC
Votes:5
Avg. Score:4.6 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:1 (25.0%)
Same OS:2 (50.0%)
From: tstarling@php.net Assigned: pierrick (profile)
Status: Closed Package: cURL related
PHP Version: 7.3Git-2018-06-15 (Git) OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: tstarling@php.net
New email:
PHP Version: OS:

 

 [2018-06-15 07:03 UTC] tstarling@php.net
Description:
------------
Calling curl_multi_select() causes the application to wait for a fixed, user-supplied timeout value. If the remaining configured timeout (according to CURLOPT_TIMEOUT etc.) is shorter than the select timeout, the configured timeout is only checked after the select timeout finishes.

This means that the user is forced to choose a short select timeout, so that configured timeouts are checked sufficiently often. The user has no easy way to derive the correct maximum select timeout.

To fix this, libcurl 7.28 introduced curl_multi_wait(), which is a select() wrapper that respects configured timeouts. I propose using this function in PHP instead of select(). Code review confirms that this has not yet been done as of today's git master.

Incidentally, HHVM has already made this change.

Test script:
---------------
<?php

$mh = curl_multi_init();
// Use address blackholed with: iptables -A INPUT -d 127.0.0.44 -j DROP
$c = curl_init('http://127.0.0.44/');
curl_setopt($c, CURLOPT_TIMEOUT, 1);
curl_multi_add_handle($mh, $c);

do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

$t = microtime(true);
while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($mh, 10) != -1) {
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
}
print round(microtime(true) - $t) . "\n";


Expected result:
----------------
1

Actual result:
--------------
10

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-08-14 02:04 UTC] pierrick@php.net
-Assigned To: +Assigned To: pierrick
 [2018-09-18 01:45 UTC] pierrick@php.net
-Status: Assigned +Status: Closed
 [2018-09-18 01:45 UTC] pierrick@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2018-10-12 15:04 UTC] mimipim at abv dot bg
Please push this fix for PHP 5.6 too!
 [2018-10-12 15:16 UTC] spam2 at rhsoft dot net
PHP5 is dead
 [2018-10-12 15:20 UTC] nikic@php.net
@mimipim: PHP 5.6 (and PHP 7.0) are no longer actively supported. As this fix is not security-related, it is not eligible to land in PHP 5.6. Please find more information on supported PHP versions at http://php.net/supported-versions.php.

As security support for PHP 5.6 will end in less than two months, you are strongly encouraged to upgrade to at least PHP 7.1.
 [2018-11-22 13:54 UTC] php at kanariepiet dot com
This has been fixed in PHP 7.1.23 and 7.2.11.

Please note the patch changes the behaviour of curl_multi_select(). Previously curl_multi_select() would return -1 if cURL has no open file descriptors. In the new situation (using curl_multi_wait() with libcurl 7.28 or higher) curl_multi_select() will return 0 if cURL has no open file descriptors.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 10:01:29 2024 UTC