使用GDB调试PHP代码,解决PHP代码死循环问题
最近在帮同事解决Swoole Server问题时,发现有1个worker进程一直处于R的状态,而且CPU耗时非常高。初步断定是PHP代码中发生死循环。 下面通过一段代码展示如何解决PHP死循环问题。 代码如下: 通过ps aux得到进程ID和状态如下,使用gdb -p 进程ptrace跟踪,通过bt命令得到调用栈 代码如下: 执行gdb后,死循环的进程会变成T的状态,表示正在Trace。这个是独占的,所以不能再使用strace/gdb或者其他ptrace工具对此进程进行调试。另外此进程会中断执行。gdb输入c后,程序继续向下运行。然后再次按下ctrl + c中断程序。 通过bt命令查看进程的调用栈。 代码如下: 两次的BT信息不一样,这是因为程序在不同的位置中断。看到execute (oparray=0x21d58b0) 这一行,这里就是PHP执行oparray的入口了。gdb下输入f 6,(通过调用栈编号可得)。 代码如下: handler(execute_data TSRMLS_CC)) > 0) {
(gdb) p *op_array
$2 = {type = 2 ' 02',function_name = 0x7f726d086540 "test",scope = 0x0,fn_flags = 134217728,prototype = 0x0,num_args = 2,required_num_args = 2,arg_info = 0x7f726d086bd8,
refcount = 0x7f726d0870f0,opcodes = 0x7f726424d600,last = 8,vars = 0x7f726424e890,last_var = 2,T = 1,brk_cont_array = 0x0,last_brk_cont = 0,try_catch_array = 0x0,
last_try_catch = 0,static_variables = 0x0,this_var = 4294967295,filename = 0x7f726424ba38 "/home/htf/wwwroot/include.php",line_start = 12,line_end = 15,doc_comment = 0x0,
doc_comment_len = 0,early_binding = 4294967295,literals = 0x7f726424eae0,last_literal = 4,run_time_cache = 0x7f726450bfb0,last_cache_slot = 1,reserved = {0x0,0x0,0x0}}
这里的filename就能看到op_array是哪个PHP文件的。然后输入f 0进入当前位置。 代码如下: 这里的lineno表示OPCODE所在的代码行数,可以到对应文件里去看下是哪行代码。使用GDB可以查看到更多的信息,这里就不再一一介绍了,有兴趣各位可以自行尝试。 zbacktrace的使用 zend官方提供了一个gdb的脚本,对指令进行了封装,可以直接看到php函数的调用关系。在php源代码包的根目录中有一个.gdbinit。使用 代码如下: 可以直接看到PHP函数的调用堆栈。 以上就是本文的全部内容了,希望大家能够喜欢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |