• 技术文章 >php教程 >php手册

    php curl_multi_select 死循环原因及相应处理办法

    2016-06-06 20:11:29原创2459

    现象 在系统更新以后,相应的php也升级到了新的版本.在运行了自己的代码之后,发现程序直接卡死不动了.在经过一阵排查之后,发现其卡在了非常诡异的地方 //use select to get response //proceed select until all handle response //can refer php.net page, c

    现象

    在系统更新以后,相应的php也升级到了新的版本.在运行了自己的代码之后,发现程序直接卡死不动了.在经过一阵排查之后,发现其卡在了非常诡异的地方

     //use select to get response
     //proceed select until all handle response
     //can refer php.net page, curl_multi_select() api
     while ($this->active && $mrc == CURLM_OK) 
     {   
         if (curl_multi_select($this->mh) != -1) 
         {   
             do {
                 $mrc = curl_multi_exec($this->mh, $this->active);
                 if ($mrc == CURLM_OK)
                 {   
                     while($info = curl_multi_info_read($this->mh))
                     {   
                         $this->process($info);
                     }        
                 }   
             } while ($mrc == CURLM_CALL_MULTI_PERFORM);
         }   
     }
    

    另外可以注意到,CPU的使用率一直100%,说明我们的程序卡死了.

    而经过一阵debug,发现程序运行到curl_multi_select之后,一直返回-1,然后就不断进入循环,卡死了.

    原因探究

    原来在10.8.5的时候,代码是能运行的,而且在linux中运行也很正常,因此,结果之后可能是php或者是相应依赖随着系统变化引起的问题.观察命名也能知道curl_multi_select其背后是基于libcurl进行实现的.而两个系统的libcurl版本也确实不同.

    通过查看curl_multi_exec,有个用户的回复引起了注意.

    Alex Palmer 10 months ago
    On php 5.3.18+ be aware that curl_multi_select() may return -1 forever until you call curl_multi_exec(). See https://bugs.php.net/bug.php?id=63411 for more information.

    查看bug列表,发现了原作者的回答:

    [2012-11-03 03:42 UTC] pierrick@php.net
    I’m not sure we really want to wait 1 second for nothing in this specific case. Furthermore, as mentioned in my commit message, when libcurl returns -1 in max_fd after calling curl_multi_fdset, it is because libcurl currently does something that isn’t possible for your application to monitor with a socket and unfortunately you can then not know exactly when the current action is completed using select().
    I would personally keep the current behaviour.

    所以显然是curl_multi_select一直返回了-1,导致了程序进入了死循环,卡死掉了.而这个是进入了php5.3.8以后,做出的改变.

    正确的curl_multi_select写法

    那在这样的behaviour下,该如何编写curl_multi_select呢.

    经过一番研究,终于找到了合适的写法.关键在于在while循环中要执行curl_multi_exec,直到处理完毕再进入select.

    实现代码:

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

    影响的php版本

    这个我没有深入探究,理论上这个是和curl以及php版本有关系.

    从其他使用者反馈的有:

    Related Posts:

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:Flash上传出现IO Error #2038的错误解决方法 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • [namespace]PHP命名空间的使用基础,namespace命名空间• php mysql 数据库类• mysql 搜索之简单应用• 日常整理PHP中简单的图形处理(经典)• PHP采集程序原理分析篇
    1/1

    PHP中文网