2011-10-22 34 views
3

我的Apache有時候因爲內存不足而死亡。這不會發生。我在這個項目中有幾百個PHP文件。如何在PHP中捕捉遞歸失控腳本?

我懷疑有一個無意的遞歸創建 - 不只是一個函數自己調用,而是函數A調用B然後再次調用A.

我試着只是讀代碼,發現這樣的遞歸,但沒有運氣。

有沒有一種方法可以告訴PHP跟蹤所有遞歸,或者在內部堆棧超過一定大小時發出警告?

+0

您可以使用xdebug獲取信息,然後檢查哪個功能需要最長時間才能完成。如果你有一個無限的遞歸函數,那麼這個函數會出現在列表的頂部,你就會有你想要的罪犯。 – Furicane

+0

我試過了,但是如果操作系統殺死了apache進程xdebug不會記錄任何信息 – Mikhail

+0

@Mikhail:您使用哪個SAPI進行PHP? CGI/FCGI/mod_php的? – hakre

回答

3

我的Apache有時因爲內存不足而死亡。

那麼這是至少有一點開始。我可以閱讀你懷疑是由PHP腳本引起的問題。

要找出哪一個,你需要看得更遠。我能想到的一種方式是啓用PHP錯誤日誌記錄。然後將memory_limit設置爲較低的值,以便在發生大量內存消耗時引發錯誤。您可以在錯誤日誌中找到發生這種情況的行(請參閱Protocol of some PHP Memory Stretching Fun)。

這應該給你一些潛在的地方。

我不是很確定,如果遞歸必須導致這種情況,並且你自己寫道你只能假設這一點。要檢測遞歸,您可以使用了XDebug和限制遞歸深度:

xdebug.max_nesting_level=<your preferred value> 

這應該給你在錯誤日誌,以及更多有用的信息。

如果內存和遞歸都不是這種情況,它可能與PHP或PHP segaults無關,並且您的web服務器無法處理這種情況。不知道mod_php如何處理segfaults,但您尚未指定您正在使用的SAPI。

但是,PHP段落錯誤的一個典型來源是在觸發pcre遞歸限制之前踢出PHP的正則表達式。如果您在代碼中使用正則表達式,那麼您可以將reduce the recursion limit設置爲較低的值,並測試是否有幫助。但是,從你的問題來看,這是否是一個原因尚不清楚。所以你首先需要了解更多。

+1

如果可以的話,會輸出+2。 – Mikhail