如何捕获 PHP 中的递归失控脚本?
我的 Apache 有时会因为内存不足而被杀死。这种情况过去并没有发生过。我在这个项目中有数百个 PHP 文件。
我怀疑无意中创建了递归——不仅仅是函数调用自身,而是函数 A 调用 B,然后函数 A 再次调用 A。
我尝试过阅读代码并找到这样的递归,但没有运气。
有没有办法让 PHP 跟踪所有递归,或者在其内部堆栈超过一定大小时发出警告?
My Apache gets killed sometimes because it runs out of memory. This did not use to happen. I have several hundred PHP files in this project.
I suspect that there was an unintentional recursion created -- not just a function calling itself, but function A calling B which then calls A again.
I've tried just reading the code and finding such recursion, but with no luck.
Is there a way I can tell PHP to keep track of ALL recursions, or throw a warning when its internal stack is over a certain size?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
嗯,这至少是一个起点。我可以在你的问题中读到你怀疑这是由 PHP 脚本引起的。
要找出哪一个,您需要进一步观察。我能想到的一种方法是启用 PHP 错误日志记录。然后将
memory_limit
设置为较低的值,这样就可以在发生大量内存消耗时引发错误。您可以在错误日志中找到发生这种情况的行(另请参阅 一些 PHP 内存拉伸乐趣的协议)。这应该会给你一些潜在的位置。
我不确定递归是否一定会导致这种情况,并且您自己写道您只是假设这一点。要检测递归,您可以使用 xdebug 并限制递归深度:
这应该会在错误日志中为您提供更多有用的信息。
如果内存和递归都不是这种情况,则可能与 PHP 或 PHP 段无关,并且您的网络服务器无法处理这种情况。例如,不知道
mod_php
如何处理段错误,但您还没有指定您正在使用的 SAPI。然而,PHP 段错误的一个典型来源是正则表达式,它会在触发 pcre 递归限制之前踢出 PHP。如果您在代码中使用正则表达式,则只需 将递归限制降低到较低的值,例如并测试这是否有帮助。但是,从您的问题来看,尚不清楚这是否是一个原因。所以你首先需要了解更多。
Well that's at least a point to start with. I could read in your question you suspect that is caused by a PHP script.
To find out which one, you need to look further. One way I could think of is that you enable PHP error logging. Then set the
memory_limit
to a low value so you can provoke errors where much memory consumption happens. You find the line where this happens in the error log (see as well Protocol of some PHP Memory Stretching Fun).This should give you some potential places.
I'm not specifically sure if recursion must cause this and you wrote yourself that you only assume that. To detect recursion, you can use xdebug and limit recursion depth:
This should give you as well more useful information in the error logs.
If both memory and recursion is not the case, it might either not be related to PHP or PHP segaults and your webserver can't handle that situation. No idea how
mod_php
deals with segfaults for example but you haven't specified the SAPI you're using anyway.A typical source of PHP segfaults however are regular expressions that kick out PHP before triggering the pcre recursion limit. If you're making use of regular expressions in your code, you can just reduce the recursion limit to a lower value like and test if that helps. However, from your question it's not clear if that is a cause at all. So you first need to find out more.