2012-10-26 88 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'參數運行該腳本的發佈