debug: 使用gdb分析nginx+fcgi后端框架

问题背景:

在linux上使用了nginx+fcgi的后端框架,cgi会偶发性地产生段错误Segfault Fault,想用gdb来定位出错原因。

1、尝试使用gdb coredump

但是cgi出现问题时,一直无法产生coredump,做了如下几个尝试:

  1. ulimit -c unlimited # 使能coredump生成
  2. sysctl -w fs.suid_dumpable=1 # 使能非root进程的coredump生成?因为此处我用的是www-data权限,非root。
  3. 保证进程对存放 core 文件的目录拥有写入权限。 nginx: master process是root权限,nginx: worker process是www-data权限,fcgiwrap也是root权限。
  4. 在配置文件 conf/nginx.conf 中增加两行配置。(但这个应该是针对nginx崩溃的情况,和cgi貌似没什么关系)
worker_rlimit_core 500m;      //core文件大小限制
working_directory core_files;   //core文件目录

以上尝试经验证全都无效,当www-data用户调用cgi程序产生错误时,就是不生成coredump。

2、gdb 直接运行程序

无效。cgi程序的参数无法直接从命令行输入,而是在代码中调用了cgi相关的库,去读取http request的相关信息。直接用gdb 直接运行程序,是无法复现出错现场的。

3、gdb attach

因为nginx+fcgi的后端框架会产生三个进程,分别为nginx的master process和worker process,以及cgi的fcgiwrap。
这里对框架不做过多介绍,只说明下调用流程是worker process → fcgiwrap → cgi程序。
因此gdb attach进程时,要attach的是fcgiwrap进程。
但这里又有一个新的问题,cgi程序执行时间通常很短,不加sleep的话,根本无法获取到进程的pid。而加了sleep,往往错误也不会产生了(因为错误可能和执行时序有关),且这个错误不是必现的,attach后有99%的概率是正常的。

这个方案一开始走不通被废弃了,但后来用下面第四种方案解决后,发现其实是可以sleep的,但不能在cgi中sleep,而是要在kernel中sleep。这样只有发生了段错误才会sleep,避免了以上问题。
这样sleep之后,即可gdb attach,查看各个线程的现场,从而定位出错原因。

4、反汇编debug

这种方法是向大神请教得到的。其实并没有用到gdb,但其中核心思想和gdb应该是一致的。
这里简要描述下,具体步骤可以参考下一篇文章。

一、修改系统内核,在出错处截获信号进入循环。
二、复现问题,获取指针地址A和进程号B。
三、根据B进程的smaps内存映射表,由A所在地址区间得到出错的库,记录库的起始地址C。
四、A-C=D,再对库进行反汇编,得到偏移量D所属的函数。
五、后面就是到代码中去定位这个函数了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值