2008-05-22

程序随笔 - 4

ESR在TAOUP的第七章讨论多道程序设计中需要避免的问题时,写下了这段话:

Threads -- Threat or Menace?

``From a complexity-control point of view, threads are a bad substitute for lightweight processes with their own address spaces; the idea of threads is native to operating systems with expensive process-spawning and weak IPC facilities.''

读到这句话时是大学毕业,并没有深刻的感受。随着项目RC2阶段的结束,有些 bug也越来越隐秘,难以调试。调试多线程的网络程序让人体会到类似量子物理 里的``测不准原理'' -- 因为竞态都是时间相关的,在调试器下观察程序的行为 使得程序本身的行为发生了改变。

1. Bug #1984

耗费了我昨天一个下午和今天一个上午,也就是整整一天,还不算昨晚在家屁颠 屁颠调试到午夜的时间。我们的C, Java和Ruby的客户端API在调用两个XML-RPC 远程调用时都会莫名奇妙的发生问题:第一次调用是成功的,第二次会失败,并 且此后的调用都会失败。因为其它类似客户端API都工作的很好,因此我怀疑是服 务器代码的问题。

手工写了服务器端代码和一个简单的客户端,服务器端只提供这个出问题的调用, 客户端工作正常。而服务器端工作也非常正常,苦闷。怀疑是 libary 兼容性的 问题。

祭出``printf大法'',一切显示服务器端的数据都很正常,而C客户端的日志显示 处理一次HTTP-read的时候读到了一次EOF。于是跟踪了一晚所用library的源代码, 无果而终。

上午回到公司,在服务器端把所用怀疑的fooDoSomething()去除:
- ret = fooDoSomething();
+ ret = 0;

一切都工作正常。OK了,那一定是fooDoSomething()的bug了,后续的调试果然证 明了这个结论。但开始时该bug只在64位平台发生,而且如果打开debug后,错误 的行为会稍有一点小变化。我想这和编译器还有代码的内存布局有关。请相关同 事做了相关fix后,天下太平。

2. Bug #2034

这是一个race-condition,出自我的代码。问题在于代码完成后为了其它同事的 方便修改了一些接口。事实上如果我的代码不是那么小心,这个竞态反而更不易 出现。这暴露出多线程程序下,对数据读写需要异常小心。因为多线程环境下, 所有数据默认都是共享的。而因此需要的加锁解锁又使得程序性能下降,印证了 ESR的在TAOUP中的论断。但不幸的是,根据``墨菲法则'',RC2的代码刚好在一小 时前冻结,于是我的补丁要大佬们在例行会议时讨论通过才能提交到svn仓库。

3. Bug #2041

不再赘述。出于对C++的迷信以及些许over-skill,虽然也不是我的bug,但再次 证明了``Lessons from Debian/OpenSSL Fiasco''中的一句话:``Try not to write clever code. Try to write well-organized code.''

标签:

0 Comments:

发表评论

<< Home