记一次Ubuntu的Bug处理的全过程
中秋的时候,经历了一次 Ubuntu Bug 的报告、解决与发布的整个过程。
这是我用 Ubuntu 四年来,第一次给它报告 Bug、提交补丁,虽然最终没有采纳我的那个补丁,但是学到了很多东西——特别是关于 Ubuntu 开发的相关流程,从报告 Bug、审核补丁到合并补丁,不到24小时,说明 Ubuntu 的开发效率真的很高!
简单地记录下!
不久以前我开始在 EPC 上使用 Ubuntu 10.10 Beta 时,就发现了一个 Bug。后来因为忙其他的,就暂时没去处理。直到昨天,我再一次碰到这个 Bug,于是决定花点时间去解决它。
这个 Bug 是:在“语言支持”处,通过拖曳来更改语言必定会失败,比如把“漢語(台灣)”从下面拖曳到上面来,就会失败。
我通过在终端运行,发现了如下的 Traceback 信息:
Traceback (most recent call last): File "/usr/lib/python2.6/dist-packages/LanguageSelector/gtk/GtkLanguageSelector.py", line 78, in wrapper res = f(*args, **kwargs) File "/usr/lib/python2.6/dist-packages/LanguageSelector/gtk/GtkLanguageSelector.py", line 1062, in on_treeview_locales_drag_end self.writeUserLanguage(envLanguage) File "/usr/lib/python2.6/dist-packages/LanguageSelector/gtk/GtkLanguageSelector.py", line 781, in writeUserLanguage self.writeUserLanguageSetting(userLanguage=languageString) File "/usr/lib/python2.6/dist-packages/LanguageSelector/LanguageSelector.py", line 201, in writeUserLanguageSetting find_string_and_replace(findString, setString, conffiles) File "/usr/lib/python2.6/dist-packages/LanguageSelector/utils.py", line 37, in find_string_and_replace os.rename(out.name, fname) OSError: [Errno 18] Invalid cross-device link
可以看到,在执行 os.rename 抛出“Invalid cross-device link”的错误。
为什么会这样呢?以前我只听说过,不能进行“跨设备”的硬链接,究竟 Language Selector 在做什么事情进行了“跨设备”?
接着我进行了简单的调试,打印出“out.name”和“fname”,发现原来它要做的事情便是:将“/tmp/XXX”移到“$HOME/.profile”!因为现代的 Linux 发行版,/tmp 均是以 tmpfs 的形式挂载的,也就是 /tmp 与 /home (或者是 / )是跨设备的。另因为 Python 的 os.rename 不支持跨设备操作,所以就出错了!
解决这个 Bug 也相当简单,只需要用更为强大的“shutil”库来进行文件的操作就行了,比如修正这个 Bug,用 shutil.move 取代 os.rename 即可!
大概理清楚后,我就先汇报了这个 Bug:Language Selector crashes when drag languages
然后再利用 Launchpad 默认的 SCM 工具:Bzr,建立了一个自己的开发分支,并在里面修正了这个 Bug:lp:~tualatrix/language-selector/bugfix-lp-645774
修正好 Bug 后,我向官方分支“lp:language-selector”发送了“Merge”的请求:Proposal to merge branch
接下来,Ubuntu 官方的人们在收到请求后,便会开始 Review(审核)并Merge(合并)。
最后,Colin Watson 负责了这个 Bug 的审核及合并工作,刚开始,他很快地给我的这个补丁给 Approve 并 Merge 了,并在官方的分支中留下了我的名字,^_^
然而,后来另一位开发者 Scott Kitterman 指出,shutil 的 move 操作不够“atomic”,可能会造成“/etc/default/locale”的破损。因此不能简单的使用 shutil.move 取代 os.rename。
于是,开发者换了一种思路:既然造成跨设备操作是因为在“/tmp”下建立了文件,那么就避免跨设备操作,直接在当前目前下创建所需的临时文件:只需要在用 tempfile.NamedTemporaryFile 时,加一个“dir”的参数,即可指定在某目录下创建临时文件。至此 Bug 完全解决,很快新版本的“language-selector”也发布了出去。
有过这次经历后,我才深刻地体会到 Ubuntu 的开发工作是十分有趣味而且高效的,我想今后我会更积极的参与其中,一些感想:
- 积极地报告 Bug,提供足够丰富的信息,甚至是自己的解决方案,将能使该 Bug 的解决尽可能的快。
- Launchpad.net 是 Ubuntu 真正的宝贵之处,报告 Bug、创建分支、审核/合并……甚至是某软件包的发布和构建,都是在上面一气呵成的,非常之好用,而且任何人都可以参与全程!
- 有了 Bzr 与 Launchpad 的紧密集成,事实上我们不需要真正的处理“补丁”,尽管在自己的分支中做就好了。Bzr 作为一个分布式的 SCM,鼓励使用分支解决问题(最好一个 Bug 一个分支),Review 和 Merge 也在统一的界面进行,效率很高。
- Ubuntu/Canonical 的开发者相当专业和敬业,在报告 Bug 的过程中,就相当于与他们一起“共事”,这将会使自己更快地成长。
嗯~我迫不及待想抓下一只虫子了!