使用 PHP 分段错误调试 Apache 的建议

get*_*nge 5 php zend-framework gdb segmentation-fault apache-2.2

每小时左右一个 Apache 子进程段。我们的网络服务器上的故障。我们正在运行带有 Apache prefork MPM 的非线程 PHP 5.2.17 Apache 模块。我已经使用一些核心转储、gdb 和来自 php 的 github repo 的这个 .gdbinit 文件运行了 httpd,在 gdb 中为每个文件输入以下命令:

dump_bt executor_globals.current_execute_data
Run Code Online (Sandbox Code Playgroud)

由于没有 gdb 或 php 解释器的内部工作经验,我无法从结果中做出任何事情。

core.22762
[0x53896ef0] () :-2118682552
[0x538977a0] () /Statement/Interface.php:113
[0x538978a0] /Zend/Db/Statement/Interface.php()

core.22791
[0x538977a0] () @:0
[0x538978a0] ()

core.5568
[0x53896ef0] () :2061035360
[0x538977a0] () :1767992432
[0x538978a0] ()

core.30384
[0x538977a0] () :0
[0x538978a0] ()

core.3091
[0x53896ef0] mysql_query():992424253
[0x538977a0] () ~:17
[0x538978a0] ()
Run Code Online (Sandbox Code Playgroud)

(core.3091 之后也显示了这一点Program terminated with signal 11, Segmentation fault.

#0  0x00002b6e7ad8d67d in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff53896ef0) at /usr/src/debug/php-5.2.17/Zend/zend_vm_execute.h:217
217                             EX_T(opline->result.u.var).var.fcall_returned_reference = return_reference;
Run Code Online (Sandbox Code Playgroud)

还有什么我可以在 gdb 中输入以获得更好的堆栈跟踪的吗?在调试 Apache 分段错误时,您还有其他操作吗?

任何帮助将不胜感激,谢谢。

小智 2

我以前见过这种情况.. 除了让 PHP 应用程序开发人员检查他们的代码,并确保您拥有 PHP 和 apache 的最新版本(来自您的发行版)之外,您无能为力。

如果您正在运行操作码缓存器(eaccelerator、APC 或 XCache),您可以尝试关闭它们,众所周知它们会导致奇怪的段错误。

过去,我们不得不为段错误系统部署一些令人印象深刻的黑客解决方案,当然是为了短期修复。例如,这个 cronjob 效果很好:

# Restart apache when a segfault is found in the most recent line of errorlog #*/5 * * * * tail -n1 /var/log/apache2/error.log | grep 'Segmentation fault' && /etc/init.d/apache2 restart

或者你可以尝试一些更聪明的东西: #*/5 * * * * /usr/bin/wget http://www.my-site.com/ -T10 -O 2> /dev/null - | grep "Hosted by" > /dev/null || /usr/local/bin/brutally_restart_apache.sh

残酷重启的地方是:

    #!/bin/sh
    /usr/sbin/apache2ctl stop
    sleep 6
    killall -9 apache2
    sleep 4
    /usr/sbin/apache2ctl start
Run Code Online (Sandbox Code Playgroud)