curl_multi_add_handle在第0行产生文件“未知”中的错误

问题描述:

我试图使用curl_multi_*同时获取多个(大约50个)URL,因为连续执行它需要很长时间。但是,执行curl_multi_add_handle时,我收到以下错误消息。curl_multi_add_handle在第0行产生文件“未知”中的错误

警告:(空)():10不未知有效的卷曲处理资源上线

下面是代码:

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

// Loop over pages and get set the URL to the cURL queue 
foreach ($htmltogetlist as $source) { 

    [...] 

    // Get a cURL handle of the current URL 
    $urls[$id]['ch'] = $this->_getCurlHandle($urls[$id]['url']); 

    // Success 
    if (gettype($urls[$id]['ch']) == 'resource' && get_resource_type($urls[$id]['ch']) == 'curl') { 
     curl_multi_add_handle($mh, $urls[$id]['ch']); // << Produces error 
    } 
} 

and $this->_getCurlHandle has:

// Set cURL handle 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch,CURLOPT_ENCODING , "gzip"); 
curl_setopt($ch, CURLOPT_REFERER, $url); 
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP'); 
curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_AUTOREFERER, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($ch, CURLOPT_TIMEOUT, 10); 

return $ch; 

什么奇怪的是,$urls[$id]['ch']curl类型的有效resource了,但我不能把它添加到$mh和错误是line 0文件unknown英寸实际上,我甚至可以执行句柄并从中得到正确的回应,所以我肯定它是有效的。我只是不能将它添加到$mh

$content = curl_exec($urls[$id]['ch']); 
$response = curl_getinfo($urls[$id]['ch']); 
print_r($response); // Works 

我知道cURL正在为多次转帐工作。例如,下面的代码(它本质上是相同的)工作。我也相信这不是因为我限制了数据库查询1当得到同样的错误,导致该问题的URL数量:

$ch1 = curl_init(); 
$ch2 = curl_init(); 

// set URL and other appropriate options 
curl_setopt($ch1, CURLOPT_URL, "http://lxr.php.net/"); 
curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/"); 

curl_setopt($ch1,CURLOPT_ENCODING , "gzip"); 
curl_setopt($ch1, CURLOPT_REFERER, $url); 
curl_setopt($ch1, CURLOPT_USERAGENT, 'PHP'); 
curl_setopt($ch1, CURLOPT_HEADER, true); 
curl_setopt($ch1, CURLOPT_AUTOREFERER, true); 
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($ch1, CURLOPT_TIMEOUT, 10); 

curl_setopt($ch2,CURLOPT_ENCODING , "gzip"); 
curl_setopt($ch2, CURLOPT_REFERER, $url); 
curl_setopt($ch2, CURLOPT_USERAGENT, 'PHP'); 
curl_setopt($ch2, CURLOPT_HEADER, true); 
curl_setopt($ch2, CURLOPT_AUTOREFERER, true); 
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($ch2, CURLOPT_TIMEOUT, 10); 

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

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

我会对这个解决方案非常感兴趣。我有同样的问题,正常curl_init工作得很好。但是,在彼此之后运行12个请求是无法接受的 - 所以我和你一样处于相同的位置。你找到了解决方案吗? – Richard

+0

@理查德我有工作,但我真的为我的生活不知道如何或为什么它现在的作品,而不是以前。我开始重构事情,试图尽量减少错误,尽可能减少代码,并突然开始工作,有趣的是,即使当我认为我恢复到原来的状态时,它仍然继续工作。所以我从无法摆脱错误到无法重现它。也许如果你可以把你的代码细分到一小部分,你可以向PHP提交一个错误报告。 – Mike

+0

我知道了:)我实际上已经向PHP报告了一个错误。 PHP友好的pierrick告诉我它与#61141的问题相同,显然这不是一个错误。对此的解决方案是进行一次休眠,因为multi_select返回-1,CURL希望等待一会儿,然后执行一次exec。 – Richard

我检查由理查德在上述意见中提到的问题#61141,并通过皮埃里克给出的解决方案确实是固定的错误我。

这是基本的多卷曲EXEC设置,如PHP手册发现:

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

然而,正确的设置应该是这样一个:

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

如果curl_multi_select返回-1,暂时停止脚本,然后运行curl_mutli_exec

欲了解更多详情:https://bugs.php.net/bug.php?id=61141

+0

这是一个老问题,甚至在我提交它之后,我无法在重构我的代码后重现它。我将这个答案标记为已接受,因为它*看起来像正确的答案,尤其是基于引用的错误中的注释。但是,如果任何人都可以使用可重复的代码(对于错误和解决方案)提供不同的解决方案,那么我将标记该答案。 – Mike

我用PHP 5.3.23遇到这个在OSX,卷曲7.30.0。该修复确保所有curl_init()在curl_multi_init()之前被调用;

从来没有见过这在其他平台上(即Linux)的