8

Explore Program:记一个奇怪的bug

 3 years ago
source link: https://zhuanlan.zhihu.com/p/362200560
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Explore Program:记一个奇怪的bug

一个人NB的不是标签

本文记录一次利用strace定位到了一个很奇怪的bug。
本文是找bug技巧系列之一。

首先介绍本文的主角strace——

strace

trace system calls and signals.

这个命令可以让你没有debugger和源代码的时候,去探究程序的行为。有时候它还能帮你解决很奇怪和困难的并且使用到了system call的bug。有一次,产品快要发布了,但是出现了一个严重的regression(以前没有的bug,现在有了),我就是用这个命令找到了其中的原因,博得了领导们的赞扬。

常用的功能

查看打开了哪些configuration file

strace -f -e trace=open <program>

查看写了哪些文件

strace -f -e trace=write <program>

常用的附加选项

  • -o <file>将输出定向到文件,比如strace-out.txt

strace -f -o strace-out.txt -e trace=execve <program>

  • -s <size>指定字符串的输出长度。有时候长字符的内容看不到,就可以用这个选项了。

The bug

有个配置程序,它会启动server,然后用来修改相应的参数,最后重新启动server,这样server就会使用最新配置的参数。但是临发布的时候,测试发现配置程序在配置完相应的参数以后,启动不了server。在之前的版本并没有发现这个bug。

这个配置程序是用Java写的,归属于另外一个组管理(简称Java组,实际上启动server这个模块也是归属于另外一个组,简称C++组。我是被抓来找bug的)。但是Java组并没有发现什么异常。而且他们认为配置程序是通过JNI调用C++来启动服务的。那么启动不了的原因肯定在C++组。

首先了解一下启动流程:配置程序在配置好参数后,会将server关掉,然后检查server有没有存在,如果没有存在,就启动server,如果还在,就等待,一直等到没有存在为止。

问题出现在等待的那一步的检查机制。server是被关掉了,但是server不知为什么变成了zombie,而检查机制仍然检测到server的pid,于是认为server还存活着,所以就一直在等在server关闭。但是从来没有代码回收zombie的server,所以就只能进入死循环等待。

bug修复也很简单,就是完善检查机制,如果发现存在pid,如果状态是zombie也认为server已经被关掉了。

但是最后的missing piece就是为什么server会变成zombie?之前的产品没有出现过这个问题。两个组都认为是对方的code造成。因为C++组认为成为zombie,是因为parent没有调用waitpid。而配置程序作为parent,当然要调用waitpid。但是Java组一直以来都没有调用waitpid ,而这又是regression,那么很显然不是由于这个问题造成的(要是,为什么之前没有?)。

经过长时间的排查仍然没有定位到原因。最后这个mystery还是通过strace找到了突破口。

而方法也很简单,使用strace来启动配置程序,然后对比没有问题的配置程序C和有问题的程序C的区别。

当时使用的命令就是:

strace -o debug.txt -f -e trace=signal <java 配置程序.jar>

通过对比发现,有问题的时候,最后会产生一个SIGCHLD的信号,但是没有问题的时候,这个信号没有产生。沿着这个线索,最后一步一步找到了bug所在。

Bug真身

这是因为Java组在最近添加的代码。代码里面会用Java的process模块开启一个进程去调用另外一个程序来配置参数。而Java的process模块在开启进程的时候会将SIGCHLD这个signal handler设置成SIG_DEF。而以前一直是SIG_IGN。而SIGCHLD信号在SIG_IGN的时候不会产生。

At the end

通过这个bug,我们可以看到strace的强大和方便,如果你能在合适的时候恰当的运用它。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK