Documentation on curl_multi_exec

curl_multi_exec = Run the sub-connections of the current cURL handle

Processes each of the handles in the stack. This method can be called whether or not a handle needs to read or write data.

mh A cURL multi handle returned by curl_multi_init(). still_running A reference to a flag to tell whether the operations are still running.

Usage, params, and more on curl_multi_exec

int curl_multi_exec ( resource $mh , int &$still_running )

mh A cURL multi handle returned by curl_multi_init(). still_running A reference to a flag to tell whether the operations are still running.

A cURL code defined in the cURL Predefined Constants.

Notes and warnings on curl_multi_exec

Basic example of how to use: curl_multi_exec

Example #1 curl_multi_exec() example

This example will create two cURL handles, add them to a multi handle, and process them asynchronously.

<?php
// create both cURL resources
$ch1 curl_init();
$ch2 curl_init();

// set URL and other appropriate options
curl_setopt($ch1CURLOPT_URL"http://lxr.php.net/");
curl_setopt($ch1CURLOPT_HEADER0);
curl_setopt($ch2CURLOPT_URL"http://www.php.net/");
curl_setopt($ch2CURLOPT_HEADER0);

//create the multiple cURL handle
$mh curl_multi_init();

//add the two handles
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);

$active null;
//execute the handles
do {
    
$mrc curl_multi_exec($mh$active);
} while (
$mrc == CURLM_CALL_MULTI_PERFORM);

while (
$active && $mrc == CURLM_OK) {
    if (
curl_multi_select($mh) != -1) {
        do {
            
$mrc curl_multi_exec($mh$active);
        } while (
$mrc == CURLM_CALL_MULTI_PERFORM);
    }
}

//close the handles
curl_multi_remove_handle($mh$ch1);
curl_multi_remove_handle($mh$ch2);
curl_multi_close($mh);

?>

Other code examples of curl_multi_exec being used

Solve CPU 100% usage, a more simple and right way:

<?php

do {
   
curl_multi_exec($mh, $running);
   
curl_multi_select($mh);
} while (
$running > 0);

?>

http://curl.haxx.se/libcurl/c/libcurl-multi.html

"When you've added the handles you have for the moment (you can still add new ones at any time), you start the transfers by call curl_multi_perform(3).

curl_multi_perform(3) is asynchronous. It will only execute as little as possible and then return back control to your program. It is designed to never block. If it returns CURLM_CALL_MULTI_PERFORM you better call it again soon, as that is a signal that it still has local data to send or remote data to receive."

So it seems the loop in sample script should look this way:

<?php
$running
=null;
//execute the handles
do {
    while (
CURLM_CALL_MULTI_PERFORM === curl_multi_exec($mh, $running));
    if (!
$running) break;
    while ((
$res = curl_multi_select($mh)) === 0) {};
    if (
$res === false) {
        echo
"<h1>select error</h1>";
        break;
    }
} while (
true);
?>

This worked fine (PHP 5.2.5 @ FBSD 6.2) without running non-blocked loop and wasting CPU time.

However this seems to be the only use of curl_multi_select, coz there's no simple way to bind it with other PHP wrappers for select syscall.

I tried Daniel G Zylberberg's function and
it was not working the way it was posted.
I made some changes to get it work and here is what I use:

function multiCurl($res, $options=""){

        if(count($res)<=0) return False;

        $handles = array();

        if(!$options) // add default options
            $options = array(
                CURLOPT_HEADER=>0,
                CURLOPT_RETURNTRANSFER=>1,
            );

        // add curl options to each handle
        foreach($res as $k=>$row){
            $ch{$k} = curl_init();
            $options[CURLOPT_URL] = $row['url'];
            $opt = curl_setopt_array($ch{$k}, $options);
            var_dump($opt);
            $handles[$k] = $ch{$k};
        }

        $mh = curl_multi_init();

        // add handles
        foreach($handles as $k => $handle){
            $err = curl_multi_add_handle($mh, $handle);           
        }

        $running_handles = null;

        do {
          curl_multi_exec($mh, $running_handles);
          curl_multi_select($mh);
        } while ($running_handles > 0);
      
        foreach($res as $k=>$row){
            $res[$k]['error'] = curl_error($handles[$k]);
            if(!empty($res[$k]['error']))
                $res[$k]['data']  = '';
            else
                $res[$k]['data']  = curl_multi_getcontent( $handles[$k] );  // get results

            // close current handler
            curl_multi_remove_handle($mh, $handles[$k] );
        }
        curl_multi_close($mh);
        return $res; // return response
}