如何处理 bug

Table of Contents

1. 确认 bug 准确位置

  • 在关键地方插入 assert,如函数参数断言、逻辑断言;
  • 跟踪调用语句,例如:Common Lisp 有 trace 函数;
  • 注意异常或返回值;
  • 查看日志;
  • 列出可能出现问题的地方,逐个排除。

找到问题后,最终目标是修复该问题,如果你不是开发者,就去 Google 搜索下是否其他人也遇到过、bug 反馈列表是否有人反馈过;如果有人反馈 bug 了,并且这个 bug 对你影响很大,你可跟踪 bug 的处理情况,或者给开源社区提交 patch。

1.1. 举个例子

某天用 Wifi 上网(平时都用有线上网),Wifi 频繁掉线,其他电脑和设备均正常,路由后台管理也未发现异常情况,那问题多半是在操作系统上。

这种情况问题一般出在 NetworkManager 服务和网卡驱动上。在掉线后,我 restart 了 NetworkManager 服务,问题仍旧,所以问题应该不出在 NetworkManager 服务上。怀疑是内核问题,重启系统在 Grub 上用老版本的内核(Fedora 默认保存 3 个版本内核)去引导系统,系统工作了一段时间并没有出问题,那就确定是新版本的内核驱动导致的。

回到有问题的内核,用 lsmod 找到 Wifi 的驱动:

$ lsmod | fgrep wifi
rtlwifi                73728  3 rtl_pci,rtl8192ce,rtl8192c_common
mac80211              749568  3 rtl_pci,rtl8192ce,rtlwifi
cfg80211              589824  2 mac80211,rtlwifi

挨个尝试 rmmod(卸载模块)后发现问题出现在 rtl8192ce 模块——只要重新 modprobe(加载模块),网络便可恢复正常。

然后去 Fedora 的 bug 列表(https://bugzilla.redhat.com)搜索下 rtl8192ce 最近有不有人反馈 bug:

search_result.png

第一条搜索结果“Wi-fi randomly not working”,和我遇到的问题一样,根据 bug 详情来看:

1、已经分配给内核团队处理;

2、等到内核更新后升级;

3、先切换到老版本的内核使用着。

2. 报告 bug

如果你发现了新 bug,那么需要将详细的错误信息收集起来,提供给开发者有助于修复。

一般来说,好的 bug 报告要包含很多关键信息,如:

对症状准确描述,不要用“不能工作了”、“无法使用了”等废话;
环境信息:软件版本、系统配置、操作系统(及版本)等;
重现步骤:当在操作什么时会出发Bug;
描述:触发 bug 后会有什么反应、提示什么信息;
你都做过哪些解决尝试?如重启软件、确认过硬盘和内存有充足空间等;
附加信息:截图、测试脚本等;

以下是一个比较好的参考例子(来自:https://bugzilla.redhat.com/show_bug.cgi?id=1202858):

Version-Release number of selected component (if applicable):
squid.x86_64 7:3.1.23-4.el6

How reproducible:
100%

Steps to Reproduce:

1. Login to RHEL 6.7 host with squid installed
2. Start squid using "service squid start"
3. Restart squid using "service squid restart"

Actual results:
All files are deleted on the machine.

Expected results: Squid is restarted.

然后将 bug 报告发送给开发者,一般的项目都有自己的 bug 反馈地方,比如 GitHub 的 Issue、Bugzilla 等。

建议你也读读这篇文章:《如何有效地报告 Bug》

2.1. 举个例子

某日刚升级到 Fedora 25,打开 Gnome 的软件管理(gnome-software),在还没有刷新完软件列表时点“软件源”,然后软件管理崩溃。

Fedora 使用了 ABRT 作为崩溃报告工具,当发生崩溃时,以运行崩溃软件的运行身份运行 gnome-abrt(比如我是用 root 运行 gnome-software 的,就用 root 来运行 gnome-abrt),然后可以看到最近的崩溃记录。

然后点“报告”,会自动把系统信息、崩溃信息上传到 Red Hat 的 bug 跟踪列表中。如果当前 bug 已经被人报告,ABRT 会有所提示:

1.png

若是该 bug 被人报告,你也可以用 Bugzilla 帐号登录上去跟踪该Bug的修复情况——如果你认为对你很重要、需要跟踪修复进度的话。点开链接后可以看到处理情况:

2.png

从图中可以看出是个新 bug,还未修复,我只需等待系统更新。

3. 如果我是开发者

1、根据 bug 报告成功触发 bug;

2、用调试器检测行为;

3、修复 bug,找出其他地方还有不有类似 bug;

4、增加测试用例。

5、从中学习,避免以后犯同样错误:

  • 错误是如何产生的、为什么会产生?
  • 以后如何预防类似的错误?
  • 其他地方还有这样的错误吗?
  • 如何更早地检测到这个错误?
  • 有不有可以自动地检测到这个错误的方法?

6、养成良好的编程习惯:

  • 编写可测的代码,代码要满足:简单性、耦合性、单一原则;
  • 防御性编程:为无法不言自明的断言写注释;
  • 单元测试。