使用GDB调试PHP代码,解决PHP代码死循环问题_php技巧_脚本之家

近年在帮同事解决Swoole
Server难点时,发掘存1个worker进度一贯处在凯雷德的图景,何况CPU耗费时间不胜高。开头判定是PHP代码中发生死循环。

复制代码 代码如下: bt#0
_zend_mm_alloc_int (heap=0x1eaa2c0, size=72,
__zend_filename=0xe43410
“/home/htf/workspace/php-5.4.27/ext/standard/array.c”,
__zend_lineno=2719,__zend_orig_filename=0xee5a38
“/home/htf/workspace/php-5.4.27/Zend/zend_hash.c”,
__zend_orig_lineno=412) at
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:1895#1
0x00000000008ceb86 in _emalloc (size=72, __zend_filename=0xe43410
“/home/htf/workspace/php-5.4.27/ext/standard/array.c”,
__zend_lineno=2719,__zend_orig_filename=0xee5a38
“/home/htf/workspace/php-5.4.27/Zend/zend_hash.c”,
__zend_orig_lineno=412) at
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2425#2
0x0000000000911d85 in _zend_hash_index_update_or_next_insert
(ht=0x2257a10, h=3972, pData=0x7ffffe0012b0, nDataSize=8, pDest=0x0,
flag=1,__zend_filename=0xe43410
“/home/htf/workspace/php-5.4.27/ext/standard/array.c”,
__zend_lineno=2719) at
/home/htf/workspace/php-5.4.27/Zend/zend_hash.c:412#3
0x00000000007767e1 in zif_array_flip (ht=1,
return_value=0x7f726424ea68, return_value_ptr=0x0, this_ptr=0x0,
return_value_used=1)at
/home/htf/workspace/php-5.4.27/ext/standard/array.c:2719#4
0x000000000093c03e in zend_do_fcall_common_helper_SPEC
(execute_data=0x7f726d04b2a8) at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:643#5
0x00000000009400e6 in ZEND_DO_FCALL_SPEC_CONST_HANDLER
(execute_data=0x7f726d04b2a8) at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:2233#6
0x000000000093b5fd in execute at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410

奉行gdb后,死循环的经过会产生T的动静,表示正在Trace。这些是独占的,所以不能够再利用strace/gdb可能别的ptrace工具对此进程展开调节和测验。其余此过程会停顿实践。gdb输入c后,程序继续向下运维。然后再一次按下ctrl

复制代码 代码如下: f 6#6
0x000000000093b5fd in execute at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410410 if ((ret
= OPLINE->handler(execute_data TSRMLS_CC)) > 0) { 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_使用GDB调试PHP代码,解决PHP代码死循环问题_php技巧_脚本之家。cache = 0x7f726450bfb0, last_cache_slot = 1, reserved =
{0x0, 0x0, 0x0, 0x0}}

复制代码 代码如下:#dead_loop.php$array
= array();for($i = 0; $i < 10000; $i++){ $array[] = $i;}include
__DIR__.”/include.php”;#include.phpwhile; $keys = array_flip;
$index = array_search, $array); $str = str_repeat; $strb =
test;}function test{ return str_replace;}

透过ps aux获得进度ID和情况如下,使用gdb -p
进度ptrace追踪,通过bt命令得到调用栈

上边通过大器晚成段代码展示怎么着缓慢解决PHP死循环难点。

复制代码 代码如下: p
**executor_globals.opline_ptr$4 = {handler = 0x93ff9c , op1 =
{constant = 1680133296, var = 1680133296, num = 1680133296, hash =
140129283132592, opline_num = 1680133296,jmp_addr = 0x7f726424ccb0, zv
= 0x7f726424ccb0, literal = 0x7f726424ccb0, ptr = 0x7f726424ccb0}, op2 =
{constant = 0, var = 0, num = 0, hash = 0, opline_num = 0, jmp_addr =
0x0,zv = 0x0, literal = 0x0, ptr = 0x0}, result = {constant = 32, var =
32, num = 32, hash = 32, opline_num = 32, jmp_addr = 0x20, zv = 0x20,
literal = 0x20, ptr = 0x20},extended_value = 1, lineno = 5, opcode = 60

  • c中断程序。 通过bt命令查看进度的调用栈。

这里的lineno表示OPCODE所在的代码行数,可以到相应文件里去看下是哪行代码。使用GDB能够查看见越多的音信,这里就不再朝气蓬勃一介绍了,有意思味各位能够活动尝试。

复制代码 代码如下:source
your_php_src_path/.gdbinitzbacktrace

能够直接看见PHP函数的调用客栈。

zend官方提供了叁个gdb的脚本,对指令张开了打包,可以向来看看php函数的调用关系。在php源代码包的根目录中有三个.gdbinit。使用

复制代码 代码如下:htf 3834 2.6 0.2 166676
22060 pts/12 揽胜+ 10:50 0:12 php dead_loop.phpgdb -p 3834 bt#0
0x00000000008cc03f in zend_mm_check_ptr (heap=0x1eaa2c0,
ptr=0x2584910, silent=1, __zend_filename=0xee3d40
“/home/htf/workspace/php-5.4.27/Zend/zend_variables.c”,__zend_lineno=182,
__zend_orig_filename=0xee1888
“/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c”,
__zend_orig_lineno=437)at
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:1485#1
0x00000000008cd643 in _zend_mm_free_int (heap=0x1eaa2c0,
p=0x2584910, __zend_filename=0xee3d40
“/home/htf/workspace/php-5.4.27/Zend/zend_variables.c”,
__zend_lineno=182,__zend_orig_filename=0xee1888
“/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c”,
__zend_orig_lineno=437) at
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2064#2
0x00000000008cebf7 in _efree (ptr=0x2584910,
__zend_filename=0xee3d40
“/home/htf/workspace/php-5.4.27/Zend/zend_variables.c”,
__zend_lineno=182,__zend_orig_filename=0xee1888
“/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c”,
__zend_orig_lineno=437) at
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2436#3
0x00000000008eda0a in _zval_ptr_dtor (zval_ptr=0x25849a0,
__zend_filename=0xee3d40
“/home/htf/workspace/php-5.4.27/Zend/zend_variables.c”,
__zend_lineno=182)at
/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c:437#4
0x00000000008fe687 in _zval_ptr_dtor_wrapper at
/home/htf/workspace/php-5.4.27/Zend/zend_variables.c:182#5
0x000000000091259f in zend_hash_destroy at
/home/htf/workspace/php-5.4.27/Zend/zend_hash.c:560#6
0x00000000008fe2c5 in _zval_dtor_func (zvalue=0x7f726426fe50,
__zend_filename=0xeea290
“/home/htf/workspace/php-5.4.27/Zend/zend_execute.c”,
__zend_lineno=901)at
/home/htf/workspace/php-5.4.27/Zend/zend_variables.c:45#7
0x0000000000936656 in _zval_dtor (zvalue=0x7f726426fe50,
__zend_filename=0xeea290
“/home/htf/workspace/php-5.4.27/Zend/zend_execute.c”,
__zend_lineno=901)at
/home/htf/workspace/php-5.4.27/Zend/zend_variables.h:35#8
0x0000000000939747 in zend_assign_to_variable
(variable_ptr_ptr=0x7f7263f8e738, value=0x7f726426f6a8) at
/home/htf/workspace/php-5.4.27/Zend/zend_execute.c:901#9
0x0000000000997ee5 in ZEND_ASSIGN_SPEC_CV_VAR_HANDLER
(execute_data=0x7f726d04b2a8) at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:33168#10
0x000000000093b5fd in execute at
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410#11
0x0000000000901692 in zend_execute_scripts (type=8, retval=0x0,
file_count=3) at /home/htf/workspace/php-5.4.27/Zend/zend.c:1315#12
0x000000000087926a in php_execute_script
(primary_file=0x7ffffe0038d0) at
/home/htf/workspace/php-5.4.27/main/main.c:2502#13 0x00000000009a32e3
in do_cli (argc=2, argv=0x7ffffe004d18) at
/home/htf/workspace/php-5.4.27/sapi/cli/php_cli.c:989#14
0x00000000009a4491 in main (argc=2, argv=0x7ffffe004d18) at
/home/htf/workspace/php-5.4.27/sapi/cli/php_cli.c:1365

上述就是本文的全部内容了,希望我们能够钟爱。

zbacktrace的使用

两遍的BT音信不相近,那是因为程序在不一致的职分中断。看见execute
那大器晚成行,这里正是PHP实行oparray的进口了。gdb下输入f 6,。

此处的filename就会见到op_array是哪位PHP文件的。然后输入f
0步向当前职责。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图