msgbartop
PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
msgbarbottom

31 Dec 08 一个低概率的PHP Core dump

PHP是个脚本语言, 错误定位容易, 编写起来速度较快..但是, 如果遇到了PHP自身的一些问题,那就会让人很恼火.
最近遇到一个很低概率的Core dump(大概是2年才出现一次), 经过和同事一起仔细分析,跟踪,终于找出了原因, 拿出来与大家分享.

先看Core文件展示的堆栈:

(gdb) bt
#0  0x000000302af2e2ed in raise () from /lib64/tls/libc.so.6
#1  0x000000302af2fa3e in abort () from /lib64/tls/libc.so.6
#2  0x000000302af62db1 in __libc_message () from /lib64/tls/libc.so.6
#3  0x000000302af6888e in _int_free () from /lib64/tls/libc.so.6
#4  0x000000302af68bd6 in free () from /lib64/tls/libc.so.6
#5  0x0000002a95bd4a8c in php_error_cb (type=1,
    error_filename=0x2a9755c608 "***********.php", error_lineno=272, format=Variable "format" is not available.
)
    at /home/huixinchen/php-5.2.4/main/main.c:803
#6  0x0000002a95c182ed in zend_error (type=1, format=0x2a95ebee68 "Maximum execution time of %d second%s exceeded")
    at /home/huixinchen/php-5.2.4/Zend/zend.c:976
#7  <signal handler called>
#8  0x000000302af6ac02 in malloc () from /lib64/tls/libc.so.6
#9  0x000000302af6fc92 in strdup () from /lib64/tls/libc.so.6
#10 0x0000002a95bd4720 in php_error_cb (type=8,
    error_filename=0x2a9755c608 "******.php", error_lineno=272, format=Variable "format" is not available.
)
    at /home/huixinchen/php-5.2.4/main/main.c:807

左分析,右分析,结论如下。

在PHP execute limit time 信号来的时候,PHP正在出错处理函数中, 这个时候,事件被响应,再次重入php_error_cb函数, 观察php_error_cb函数:

static void php_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args){
    ....
    if (display) {
        if (PG(last_error_message)) {
            free(PG(last_error_message));
        }
        if (PG(last_error_file)) {
            free(PG(last_error_file));
        }
        PG(last_error_type) = type;
        PG(last_error_message) = strdup(buffer);
        PG(last_error_file) = strdup(error_filename);
        PG(last_error_lineno) = error_lineno;
    }
   ....
}

我们可以看到,在php_error_cb中, 会对上一次的错误文件名进行free操作, 并对当前错误文件名分配内存.
如果, 当php执行到free了旧的错误文件名以后, 响应了事件, 于是分配新的错误文件名内存这一步并没有被执行..

这个时候, 事件响应以后,又再一次进入到了php_error_cb函数, 当再次执行free(PG(last_error_file))的时候, 会导致core dump

另外,发现PHP(*nix下)是通过调用setitimer来实现脚本超时处理的。

具体代码可以grep zend_set_timeout

转一个可以较大概率重现这个Core的脚本(By Lili):

<?php
set_time_limit(1);

while(1) {

    $a = $arr['index_miss'];

    $a = $arr['index_miss'];

    $a = $arr['index_miss'];

    $a = $arr['index_miss'];

    $a = $arr['index_miss'];

    $a = $arr['index_miss'];

}
?>


分享到:



Related Posts:

Tags: , ,

7 Responses to “一个低概率的PHP Core dump”

  1. 风雪之隅-鸟哥文章汇总 | 互联网菜鸟 |

    [...]   HTTP1.0下HTTP_HOST为空  一个巧妙的分页方法 31 Dec 08 一个低概率的PHP Core dump 21 Feb 09 PHP字符串比较 26 May 09 PHP+Gtk实例(求24点) [...]

  2. zend_signal in PHP 5.4 | 风雪之隅 |

    [...] crash的案例:深入理解PHP内存管理之一个低概率Core的分析和一个低概率的PHP Core dump , 在其中, 我说过, 其实PHP在关键操作的时候, [...]

  3. 一个低概率的PHP Core dump | 万维网黑客联盟 |

    [...] 本文地址: http://www.laruence.com/2008/12/31/647.html [...]

  4. 张二 |

    话说,为啥sudo ulimit -c unlimited 了,还是没有core dump的输入哩……当然,已经–enable-debug过了。

  5. zvaly |

    我想知道你是怎末左分析、右分析的。。。。。。

  6. 雪候鸟 |

    @truemyth, 恩,2年见一次.

  7. truemyth |

    这个比较汗…
    这种情况应该很少见吧,都到出错处理了刚好又到limit time了.

Leave a Reply

*