生成一个gdb回溯

生成一个gdb回溯
注意到PHP崩溃
有没有绝对的方式知道PHP崩溃,但可能有迹象。通常情况下,如果你访问一个总是应该生成输出的页面(例如,有一个前导HTML块),并且突然从浏览器中获得“Document contains no data”,这可能意味着PHP在执行脚本。另一种告诉PHP崩溃的方法是查看Apache错误日志,寻找SEGV(Apache 1.2)或Segmentation Fault(Apache 1.3)。
重要!
要获得正确信息的回溯,您必须将PHP配置为–enable-debug!
如果你还没有核心文件:
从你的shell中删除你对核心转储大小的任何限制:

tcsh: ulimit coredumpsize
bash/sh: ulimit -c unlimited

确保运行PHP的目录或启用PHP的httpd对运行PHP的用户具有写权限。
导致PHP崩溃:
PHP的CGI:只需运行PHP的脚本,崩溃它
PHP的Apache模块:运行httpd -X,并访问崩溃PHP的脚本
在Linux上获得核心的通用方法
设置核心模式(以root身份运行此命令):

echo "<cores dir>/core-%e.%p" > /proc/sys/kernel/core_pattern

确保目录是可写的PHP
设置ulimit(见上面如何做到这一点)。
重新启动/重新运行PHP。
之后,包括PHP在内的系统崩溃的任何进程都会将其核心文件保留在您在core_pattern中指定的目录中。

一旦你有核心文件:
运行带有启用PHP或PHP的httpd二进制文件的路径的gdb,以及核心文件的路径。一些例子:

gdb /usr/local/apache/sbin/httpd /usr/local/apache/sbin/core
gdb /home/user/dev/php-snaps/sapi/cli/php /home/user/dev/testing/core

在gdb提示符下运行:
(gdb) bt
如果你不能得到一个核心文件:
在gdb下运行httpd -X,如下所示:
gdb /usr/local/apache/sbin/httpd
(gdb)运行-X
然后使用您的网络浏览器并访问您的服务器来强制崩溃。您应该看到一个gdb提示符出现,并显示一条消息指出崩溃。在这个gdb提示符下,输入:

(gdb) bt

或者从命令行运行

gdb /home/user/dev/php-snaps/sapi/cli/php
(gdb) run /path/to/script.php
(gdb) bt

这应该产生一个回溯,你应该提交错误报告,以及任何其他的细节,你可以给我们关于你的设置,和冒犯脚本。

定位哪个函数调用导致段错误:
你可以用gdb轻松找到导致段错误的函数调用。首先,您需要一个核心文件或者在gdb下生成一个segfault,如上所述。

在PHP中,每个函数都是由一个内部调用的函数执行的, execute()并有自己的堆栈。该bt命令生成的每一行表示一个函数调用堆栈。通常情况下,execute()您发行时会看到多行bt。你对最后一个execute()堆栈感兴趣 (即最小的帧数)。您可以使用移动当前正在工作的堆叠 up,down或 frame命令。下面是一个gdb会话的例子,可以作为如何处理你的段错误的指导。

示例gdb会话

(gdb) bt
#0  0x080ca21b in _efree (ptr=0xbfffdb9b) at zend_alloc.c:240
#1  0x080d691a in _zval_dtor (zvalue=0x8186b94) at zend_variables.c:44
#2  0x080cfab3 in _zval_ptr_dtor (zval_ptr=0xbfffdbfc) at zend_execute_API.c:274
#3  0x080f1cc4 in execute (op_array=0x816c670) at ./zend_execute.c:1605
#4  0x080f1e06 in execute (op_array=0x816c530) at ./zend_execute.c:1638
#5  0x080f1e06 in execute (op_array=0x816c278) at ./zend_execute.c:1638
#6  0x080f1e06 in execute (op_array=0x8166eec) at ./zend_execute.c:1638
#7  0x080d7b93 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at zend.c:810
#8  0x0805ea75 in php_execute_script (primary_file=0xbffff650) at main.c:1310
#9  0x0805cdb3 in main (argc=2, argv=0xbffff6fc) at cgi_main.c:753
#10 0x400c91be in __libc_start_main (main=0x805c580 
, argc=2, ubp_av=0xbffff6fc,
               init=0x805b080 <_init>, fini=0x80f67b4 <_fini>, rtld_fini=0x4000ddd0 <_dl_fini>,
               stack_end=0xbffff6ec) at ../sysdeps/generic/libc-start.c:129
(gdb) frame 3
#3  0x080f1cc4 in execute (op_array=0x816c670) at ./zend_execute.c:1605
(gdb) print (char *)(executor_globals.function_state_ptr->function)->common.function_name
$14 = 0x80fa6fa "pg_result_error"
(gdb) print (char *)executor_globals.active_op_array->function_name
$15 = 0x816cfc4 "result_error"
(gdb) print (char *)executor_globals.active_op_array->filename
$16 = 0x816afbc "/home/yohgaki/php/DEV/segfault.php"
(gdb) 

在这个会话中,第3帧是最后一个execute() 呼叫。该frame 3命令将当前工作堆栈移动到适当的框架。 打印函数名称。在示例gdb会话中, 调用正在导致段错误。如果您知道内部数据结构,您可以打印您喜欢的任何内部数据。请不要问如何使用gdb或关于内部数据结构。有关gdb用法的信息,请参阅gdb手册,有关内部数据结构的信息,请参阅PHP源代码。

print (char *)(executor_globals.function_state_ptr->function)->common.function_name
pg_result_error()

你可能不会看到executesegfault是否发生,而不会调用任何函数。
https://bugs.php.net/bugs-generating-backtrace.php

猜你喜欢

转载自blog.csdn.net/q601115211/article/details/78963496