警惕由eAccelerator导致的Apache进程崩溃

警惕由eAccelerator导致的Apache进程崩溃

 

一、现象描述

某业务在访问量增大后,其服务器出现了Apache的worker进程频繁发生段错误退出的现象,查看error_log发现有如下记录:

[notice] child pid 17109 exit signal Segmentation fault (11)

 

二、示例

经过排查,发现在高并发时,eAccelerator可能导致以上的问题。

经过试验,发现下面简单的PHP脚本就可能会造成Segmentation Fault (测试环境是Apache + PHP (5.2.5) +  EA (0.9.5.3):

    function test($option =array('ab3kfksdfksdf233r3' => 'abckd'))
    {
        return'asdfsdfasdfiiis';
    }
    echo test();

三、问题的根源

导致这个问题的根本原因是,在多核机器上,PHP内核中对变量引用计数的加减不是原子操作。PHP中的每个值都是用一个zval_struct结构来表示,其中对变量的引用计数refcount的增减操作是非原子性的。

struct _zval_struct {

         zvalue_value  value;         

         zend_uint  refcount;/*zend_uintunsigned int*/

         zend_uchar  type;    

         zend_uchar  is_ref;

};

那到底是什么原因导致进程崩溃呢?我们来一步步揭开其根源。

 3.1 eAccelerator工作原理

当apache处理php脚本请求时,会调用php模块在apache中的注册的钩子函数php_handler,在这个函数中会进行一些检查、初始化等操作,然后调用zend_execute_scripts来执行具体的脚本。zend_execute_scripts执行时会先调用zend_compile_file对脚本进行编译,生成zend_op_array,然后再调用zend_execute来执行这个字节码。

如果php脚本没有被修改过,那么每次执行前都对脚本进行编译是没有必要的,而且编译是一个比较耗资源的过程。php的eAccelerator(以下简称EA)模块的作用就是减少这个编译过程,加速脚本执行。具体做法是挂入钩子函数:

         zend_compile_file= eaccelerator_compile_file;

这样zend引擎每次编译脚本时,实际是调用的eaccelerator_compile_file,EA在这个函数中对zend_op_array做了一层cache,如果发现文件最近没有修改过,并且启用了caching机制,就会直接从cache中读取并恢复zend_op_array,然后返回这些字节码以便后续执行。如果文件有修改过,则会重新编译一份,存在EA的cache中然后并返回编译的脚本字节码,如下图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值