使用Nginx post_action配置 & filter模块中添加定时器 导致的coredump

来源:互联网 发布:淘宝质量问题退货邮费 编辑:程序博客网 时间:2024/05/19 14:16


开发环境使用nginx + lua;一次使用nginx 的post_action功能,挂在某模块的添加定时器事件的接口上。

首先说下post_action功能,它会在http请求结束时产生一个新请求,产生一个内部跳转。


server {
        listen  80;
        server_name www.a.com;


        location / {
                proxy_set_header Host "www.a-upstream.com";
                proxy_pass http://127.0.0.1:8000;
                post_action @action;
        }


        location @action {
                proxy_set_header Host "www.a-post-action.com";
                proxy_pass http://127.0.0.1:8001;
        }
}

这样,http://www.a.com/访问结束时,将产生一个内部跳转请求,跳转到@action,访问上游www.a-post-action.com。查看网上资料,这种方式可以用来统计服务器的数据。


假设产生问题的filter模块为A,A的filter函数中,主要完成以下几件事情:

1. 如果没有ctx,则创建ctx;

2. 初始化ctx,ctx中包含一个定时器,定时器回调用来定时统计一个数据;定时器的内存从r->pool中分配;

3. ctx添加cleanup回调;

4.挂载ctx;


在我的测试环境中使用post_action功能,发现访问几次post_action后,产生了coredump信息。


刚开始怀疑r的内存出现了问题,就配置单个worker进程,gdb worker,p了下r的内存是没有任务问题的。这个假设推翻了。

后来有怀疑A模块中定时器的使用方式,查看nginx中其他地方,也是没有问题的。

突然,就给A模块的定时器添加函数和cleanup函数添加了打印信息,分别打印定时器的添加和消费,以及清除事件,发现居然有一个主请求的定时器事情既没有消费,也没有销毁。所以就推断,可能这个定时器使用的内存空间,也就是原来的主请求已经销毁了,内存也非法了。当然后续请求的定时器操作接口遍历时出现了问题。


那么确认下到底什么地方直接退出了定时器的消费或者回收?


进一步添加打印信息,原来是进入cleanup函数中,判断A模块的ctx为空,直接退出了。无法从ctx中获取定时器,并销毁。


进一步通过gdb的watch命令观察A模块的ctx什么时候被清空,发现原来是post_action请求执行前,会首先清空主请求的ctx,才导致了之前的主请求定时器没有销毁。但是主请求释放了,定时器的内存已经非法了。











阅读全文
0 0
原创粉丝点击