2012-10-26 69 views
25

我正在运行导致分段错误的命令行PHP作业。这项工作已经工作了很长一段时间,但它处理的是通过电子邮件发送的东西。显然这封电子邮件里有一些东西是打破它的,但我不知道是什么。如果我把核心文件在gdb,它真的没有帮助:如何诊断此PHP分段错误?

​​

如果我做一个“BT”,我只是得到这个“匹配”语句一遍又一遍。以下是头几个:

#1 0x000000000046ef1e in match (
    eptr=0x1370a887 "/td>\n\t\t\t\t\t\t\n\t\t\t\t\t</tr>\n\t\t\t\t\t\n\t\t\t\t</table>\n\t\t\t</td>\n\t\t</tr>\n\t\t\n\t\t<tr>\n\t\t\t<td style=\"border-top:3px solid #efefef; padding:20px 10px;\">\n\t\t\t\t<table style=\"width:100%;\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\n", '\t' <repeats 12 times>, "\n\t\t\t\t"..., ecode=0x133dc3a5 "_", mstart=<value optimized out>, markptr=<value optimized out>, 
    offset_top=<value optimized out>, md=0x7fffb4b1b620, ims=0, eptrb=0x0, flags=0, rdepth=17679) at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:803 
#2 0x0000000000479789 in match (
    eptr=0x1370a887 "/td>\n\t\t\t\t\t\t\n\t\t\t\t\t</tr>\n\t\t\t\t\t\n\t\t\t\t</table>\n\t\t\t</td>\n\t\t</tr>\n\t\t\n\t\t<tr>\n\t\t\t<td style=\"border-top:3px solid #efefef; padding:20px 10px;\">\n\t\t\t\t<table style=\"width:100%;\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\n", '\t' <repeats 12 times>, "\n\t\t\t\t"..., ecode=0x133dc5ca "V\002%\033U\002.", mstart=<value optimized out>, 
    markptr=<value optimized out>, offset_top=<value optimized out>, md=0x7fffb4b1b620, ims=0, eptrb=0x0, flags=0, rdepth=<value optimized out>) 
    at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:1623 
#3 0x000000000046ef1e in match (
    eptr=0x1370a886 "</td>\n\t\t\t\t\t\t\n\t\t\t\t\t</tr>\n\t\t\t\t\t\n\t\t\t\t</table>\n\t\t\t</td>\n\t\t</tr>\n\t\t\n\t\t<tr>\n\t\t\t<td style=\"border-top:3px solid #efefef; padding:20px 10px;\">\n\t\t\t\t<table style=\"width:100%;\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\n", '\t' <repeats 12 times>, "\n\t\t\t"..., ecode=0x133dc3a5 "_", mstart=<value optimized out>, markptr=<value optimized out>, 
    offset_top=<value optimized out>, md=0x7fffb4b1b620, ims=0, eptrb=0x0, flags=0, rdepth=17677) at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:803 
#4 0x0000000000479789 in match (
    eptr=0x1370a886 "</td>\n\t\t\t\t\t\t\n\t\t\t\t\t</tr>\n\t\t\t\t\t\n\t\t\t\t</table>\n\t\t\t</td>\n\t\t</tr>\n\t\t\n\t\t<tr>\n\t\t\t<td style=\"border-top:3px solid #efefef; padding:20px 10px;\">\n\t\t\t\t<table style=\"width:100%;\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\n", '\t' <repeats 12 times>, "\n\t\t\t"..., ecode=0x133dc5ca "V\002%\033U\002.", mstart=<value optimized out>, 
    markptr=<value optimized out>, offset_top=<value optimized out>, md=0x7fffb4b1b620, ims=0, eptrb=0x0, flags=0, rdepth=<value optimized out>) 
    at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:1623 
#5 0x000000000046ef1e in match (
    eptr=0x1370a885 "\t</td>\n\t\t\t\t\t\t\n\t\t\t\t\t</tr>\n\t\t\t\t\t\n\t\t\t\t</table>\n\t\t\t</td>\n\t\t</tr>\n\t\t\n\t\t<tr>\n\t\t\t<td style=\"border-top:3px solid #efefef; padding:20px 10px;\">\n\t\t\t\t<table style=\"width:100%;\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t\n", '\t' <repeats 12 times>, "\n\t\t"..., ecode=0x133dc3a5 "_", mstart=<value optimized out>, markptr=<value optimized out>, 
    offset_top=<value optimized out>, md=0x7fffb4b1b620, ims=0, eptrb=0x0, flags=0, rdepth=17675) at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:803 

我真的很茫然。我试过在strace中运行这个命令,它似乎是PEAR Mail_Queue库中的一部分。这里的strace的结束(一些身份信息已被删除):

lstat("/src/prod/releases/20121025202143/www/application/pear/MDB2/Driver/mysql.php", {st_mode=S_IFREG|0770, st_size=55723, ...}) = 0 
lstat("/src/prod/releases/20121025202143/www/application/pear/MDB2/Driver", {st_mode=S_IFDIR|0770, st_size=4096, ...}) = 0 
lstat("/src/prod/releases/20121025202143/www/application/pear/MDB2", {st_mode=S_IFDIR|0770, st_size=4096, ...}) = 0 
lstat("/src/prod/releases/20121025202143/www/application/pear", {st_mode=S_IFDIR|0770, st_size=4096, ...}) = 0 
open("/src/prod/releases/20121025202143/www/application/pear/MDB2/Driver/mysql.php", O_RDONLY) = 6 
fstat(6, {st_mode=S_IFREG|0770, st_size=55723, ...}) = 0 
fstat(6, {st_mode=S_IFREG|0770, st_size=55723, ...}) = 0 
fstat(6, {st_mode=S_IFREG|0770, st_size=55723, ...}) = 0 
mmap(NULL, 55723, PROT_READ, MAP_SHARED, 6, 0) = 0x2b49f7bb4000 
brk(0x987b000)       = 0x987b000 
brk(0x98bb000)       = 0x98bb000 
munmap(0x2b49f7bb4000, 55723)   = 0 
close(6)        = 0 
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 6 
fcntl(6, F_SETFL, O_RDONLY)    = 0 
fcntl(6, F_GETFL)      = 0x2 (flags O_RDWR) 
fcntl(6, F_GETFL)      = 0x2 (flags O_RDWR) 
fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK) = 0 
connect(6, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("IP ADDRESS TO DB SERVER REMOVED")}, 16) = -1 EINPROGRESS (Operation now in progress) 
fcntl(6, F_SETFL, O_RDWR)    = 0 
poll([{fd=6, events=POLLIN|POLLPRI}], 1, 60000) = 1 ([{fd=6, revents=POLLIN}]) 
setsockopt(6, SOL_SOCKET, SO_RCVTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0 
setsockopt(6, SOL_SOCKET, SO_SNDTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0 
setsockopt(6, SOL_IP, IP_TOS, [8], 4) = 0 
setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0 
setsockopt(6, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 
poll([{fd=6, events=POLLIN}], 1, 60000) = 1 ([{fd=6, revents=POLLIN}]) 
read(6, "C\0\0\0\n5.1.37-1ubuntu5.5-log\0Q\257\3\0009"..., 16384) = 71 
write(6, "=\0\0\1\205\242\2\0\0\0\[email protected]\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65) = 65 
read(6, "\7\0\0\2\0\0\0\2\0\0\0", 16384) = 11 
poll([{fd=6, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout) 
write(6, "\10\0\0\0\2xxxxx", 12)  = 12 
read(6, "\7\0\0\1\0\0\0\2\0\0\0", 16384) = 11 
lstat("/src/prod/current/www/application/pear/Mail/mime.php", {st_mode=S_IFREG|0770, st_size=50252, ...}) = 0 
lstat("/src/prod/current/www/application/pear/Mail", {st_mode=S_IFDIR|0770, st_size=4096, ...}) = 0 
lstat("/src/prod/current/www/application/pear", {st_mode=S_IFDIR|0770, st_size=4096, ...}) = 0 
lstat("/src/prod/current/www/application", {st_mode=S_IFDIR|0776, st_size=4096, ...}) = 0 
--- SIGSEGV (Segmentation fault) @ 0 (0) --- 
+++ killed by SIGSEGV +++ 
Segmentation fault 

如果任何人有任何意见或指针的调查路线,我真正体会到它。我真的很难过这个。

+4

看起来像'preg_match'中的一个stackoverflow,可能是由真正的病态输入引起的。你可以试着找出你的脚本的哪一行导致问题,然后确定函数的输入是什么,然后提交一个PHP错误报告:) – nneonneo

+0

你是否设法解决这个问题?看起来你正在运行2010年12月发布的PHP 5.3.4,你是否尝试更新到更新的版本? –

回答

32

如果遇到段错误,我通常会使用xdebug。我更喜欢使用下面一行:

php -d xdebug.auto_trace=ON -d xdebug.trace_output_dir=mytracedir/ myscript.php 

随着下mytracedir /跟踪输出,可以方便地计算出近似PHP的线,它打破了脚本。然后在每行的一条语句中重写该行,并使用error_log()来调试变量。如果使用__destruct()或__toString(),那么它可能会更棘手。

请参阅http://xdebug.org/docs/execution_trace了解更多信息。

(如果分机未加载,但安装后,尝试添加php -dzend_extension=xdebug.so [...]

+0

这也会崩溃。虽然它是一个很好的工具;) – hakre

+1

是的,但是你可以看到PHP进程在崩溃之前走了多远。如果你有多条可能的线路崩溃(PCRE递归),你有更好的机会找到合适的线路。至少,我会这样做;-) – Trendfischer

+1

对,好点。你也可以用xdebug和远程调试来做到这一点。应该可以在GDB中启动会话。 +1。 – hakre

10

调试器已经告诉你会发生什么:

... rdepth=17680) at /home/farmer/srcs/php-5.3.4/ext/pcre/pcrelib/pcre_exec.c:470 

pcre.recursion_limit setting

PCRE .recursion_limit - PCRE的递归限制。请注意,如果将此值设置为较高的数值,则可能会消耗所有可用的进程堆栈,并最终导致PHP崩溃(由于达到了操作系统规定的堆栈大小限制)。

减少它的值,以便它不会再为快速修复而崩溃。然后你会看到你的HTML没有被正则表达式完全处理。

改进表达式不要太依赖递归。您可能只想使用HTML解析器。

1

尝试从命令行php.ini中删除memcache.so并禁用opcache,其中包括opcache部分注释。使用-c path/php.cli.ini和'-d memory_limit -1'参数运行该脚本的发布