如何处理 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:
第一条搜索结果“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 会有所提示:
若是该 bug 被人报告,你也可以用 Bugzilla 帐号登录上去跟踪该Bug的修复情况——如果你认为对你很重要、需要跟踪修复进度的话。点开链接后可以看到处理情况:
从图中可以看出是个新 bug,还未修复,我只需等待系统更新。
3. 如果我是开发者
1、根据 bug 报告成功触发 bug;
2、用调试器检测行为;
3、修复 bug,找出其他地方还有不有类似 bug;
4、增加测试用例。
5、从中学习,避免以后犯同样错误:
- 错误是如何产生的、为什么会产生?
- 以后如何预防类似的错误?
- 其他地方还有这样的错误吗?
- 如何更早地检测到这个错误?
- 有不有可以自动地检测到这个错误的方法?
6、养成良好的编程习惯:
- 编写可测的代码,代码要满足:简单性、耦合性、单一原则;
- 防御性编程:为无法不言自明的断言写注释;
- 单元测试。