DongHao: 08 2010存档

蜂蜜

| | Comments (2) | TrackBacks (0)

爸以前跑车,曾经在养蜂人那里买了一些野蜂蜜,香味扑鼻、非常浓稠,气温偏低就会结晶,确是正宗好蜂蜜。

我睡觉不沉,喝蜂蜜可以安神助眠,所以用量不小。现在蜂蜜快喝完了,爸又不可能为了买蜂蜜再回一趟家乡,超市里的蜂蜜不用考虑了,不知道兑了多少水,看着跟糖稀似的。琢磨着在北京附近有没有散装的好蜜出售。


于是乎,周五爸妈去了趟香山,顺路去了植物园,买了些蜂蜜。

我尝了尝新买回来的蜂蜜,也很香,喝了一点,

“不错,好甜......比家乡的那个要甜的多”

“可能是品种不同,不同的花,产出的蜜不一样” 爸一边回答一边看盒子上自己贴的标签:“这是枣花蜜......嗯,这是荆条蜜......”

家乡的蜜香味重甜味淡,似乎更极品,是什么花的蜜呢?我好奇的拿起老瓶子看了一眼标签,上面写着——

“遵义蜜”

客服琐记

| | Comments (2) | TrackBacks (0)
客户用我们提供的API时居然出现了程序死循环。

我们的API用户已经使用了快一年了,还从没遇到这种情况,多半应该是用户使用上的问题。所以我下楼去看看。

客户的问题很容易重现,但是我写了个一样的例子,却没有这个问题。

“我的例子跟你代码几乎一样啊”我问。

“是啊......不对,有点不一样,你是多进程,我是多线程的,你们的API里用到了read,而且还判断了errno是吧,errno在多线程下岂不是互相影响?”

他这么一说我还真有点怀疑了,虽然API已经被用了一年,但大多数人都是用的多进程(unix的优秀习惯,噢),这可能是大家都没发现这一问题的原因。

我跑去问架构师,说了一下我的怀疑。

“不会吧,linux上系统调用都有可能影响errno,那任何一个多线程程序岂不是都有这个问题?”

“对啊。。。”

我这个人很动摇,两头都在说我就两头都在晃。

架构师查了查errno的man,确实,errno是“thread local”的,一个线程一个errno,不会互相干扰。

干脆回去把我的例子改成多线程的,依然不能重现,这下就不是多线程的问题了。


最后用户突然想起他们有个线程比较特殊,它@X%X%@#¥%……&*,还是API使用上的问题。我松口气。

对自己写的kernel module进行压力测试,连续跑了24小时,没啥问题,但是,继续跑到30几个小时的时候,内核panic了。

从panic的信息看,是在dcache_readdir的时候,就是从cache里读各inode的时候遇到麻烦了。

kernel本身是很坚固的,肯定是我的module某个地方把cache里的东西弄坏了,想想我确实有遍历目录的操作:

next = dentry->d_subdirs.next;
while (next != &dentry->d_subdirs)
......

再仔细看看内核里dcache_readdir的实现,喔,我少加了锁,应该是:

spin_lock(&dcache_lock);
遍历目录
spin_unlock(&dcache_lock);

之前的panic应该是我遍历目录的同时系统在调整dcache,结果竞争了。

那些找实习或找工作都很顺利的、成绩优秀的、拔尖的、外企都抢着要的人才们,请忽略此文。

5年前我找实习,很艰难。最近招聘实习生,有一个我面试感觉还可以的实习生来了一封邮件,看此邮件,我感到既同情又无奈:

您好!

       我是xxx,上周二去贵公司面试了实习生的职位。到今天已经一周了,还是没有得到通知,应该是面试没有通过被默拒了吧。自己等的也比较着急。

       还是想冒昧的问一下:在面试时应该怎样表现,或者是怎样准备知识更好,能否给点建议。说实话,这三周实习的过程中悲剧了几次,但都不是很清楚企业筛选的标准。

       如果您有时间,就简单回复下吧。谢谢!


我回了邮件,原文贴在这里,一字不改:

您好:

        我刚问了leader,确实是拒了。

        就我个人来说,我觉得你的面试表现不错,基础知识比较扎实,回答也比较迅速得体,我挑不出什么明显的问题。但是,我只是公司一个普通程序员,不是管理层,决定不了你的去留。我问了你被拒的原因:各个项目组需要的是迅速能上手的人或者说专业对口的人,你专业不够对口,同时缺乏项目经验。

       你可能会觉得不公平:本来我就是找实习,怎么还要项目经验??本来我学的是软件工程,做的就是软件,有什么不对口的? 这个问题我也没有办法回答,我当年找实习一样也有这样的愤慨,但是世道艰难,5年了,也没人回答我。

        你邮件里的意思,你已经找了三周的实习而没有结果,这个你不用着急,我也是软件学院的,05年找实习的时候,花了将近两个月,面试过intel、sun、IBM还有很多你根本没听说过的小公司,最后是在3721公司(就是那个著名的流氓公司)实习。

        现在世道艰难,招聘公司也是挑肥拣瘦,所以花的时间肯定是越来越长,你的基础不错,所以不要太着急,小公司(甚至流氓公司)实习也可以考虑,只要是工作能长经验就好。

        对了,我们核心系统组拒了,但是测试组还在招实习生,你个人愿意干测试工作吗?相对开发工作,是要枯燥一些。


和我当年一样艰难的实习生们,你们也只能和我当年一样的继续艰难了。

真的不知道还能说什么。


====== 2010.08.11更新 ======
今早和leader再商量了一下,决定收这位实习生。先做一个月的测试工作适应团队,再考虑转为开发。
leader本身是出于好意:我们选择实习生除了专业选择,也要考虑我们带实习生的资源是否丰富。如果带的资源不够,那么实习生学不到东西,带的人疲惫,两边都不好过。
呵呵,我的回信有点夸张,至少我们招聘并非”挑肥拣瘦“,是双向选择,也有拒了我们的实习生。我这样直肠子的大炮,夸张就夸张了,大家慢慢习惯。

同时感谢大家的关心。

趣事二则

| | Comments (2) | TrackBacks (0)
7月底,桑拿天。

妈:昨晚热得不行了。我吹个电扇,你爸又嫌冷;我盖被单,你爸盖被子,没法过了。

我:要不买个空调吧。

妈:你爸吹个电扇都怕,还空调?!

我:这样,空调买回家,不用安装,内机对着你吹,外机对着爸吹,这样都满意了。



家里办理宽带通,两年,妈叫他们送点礼品,宽带通的人说没礼品,还说歹说送了个金山的杀毒软件。

几天后,家里的小床腾了出来,打算卖掉。

我:单卖可能卖不了多少钱。

妈:那就把床垫搭送了。

我:也没多少钱。

妈:那就买单人床一个,搭送杀毒软件一份。

项目一直是有自动化测试的,每天都跑一遍,把结果报告发给团队的每个人。

过去几个月自动化测试跑得都很顺利,太顺利了,每天都没有fail。

写这些用例的人有些离职了。

现在项目有大改动,很多自动case跑fail了,我们知道是哪个case fail,但是,这个case具体是做了些什么才fail的呢?没人知道了,测试人员、包括开发人员,都只能去看自动测试的code来找出原因和重现方法......这样,所谓“自动化测试”,变成了“半自动化测试”??虽然你能告诉我某个case出错了,但你没有告诉我是怎么出错的、怎样重现?

最基本的解决办法是在自动化测试的code里加入足够的用例说明,如果fail了,至少可以很快知道怎么去手工重现。唉,慢慢改吧。

内核模块里自己做了一个简化版的 find_get_page:

  struct page * my_get_page(struct address_space *mapping, unsigned long offset)
  {
      struct page *page;

      read_lock_irq(&mapping->tree_lock);
      page = radix_tree_lookup(&mapping->page_tree, offset);
      read_unlock_irq(&mapping->tree_lock);
      return page;
  }

代码是从2.6.18的内核里抄来的。

在2.6.9内核的xen虚拟机上测试,现象很诡异:服务器的ssh连接突然断开,只能重连,重连后看见模块被自动卸载掉了。仔细看代码,才发现2.6.9内核的struct address_space里的tree_lock是spinlock_t,而不是rwlock_t,结果我的代码就是对着一个spinlock_t调用read_lock_irq,锁操作不对,然后又发生了什么呢?

read_lock_irq 调用了 _raw_read_lock:

  static inline void _raw_read_lock(rwlock_t *rw)
  {
  #ifdef CONFIG_DEBUG_SPINLOCK
      BUG_ON(rw->magic != RWLOCK_MAGIC);
  #endif
      __build_read_lock(rw, "__read_lock_failed");
  }

喔,kernel会判断锁的magic number,不对的话会调用BUG_ON(),进而调用BUG(),所以机器打了个嗝。

如果没有这个magic number的检测,一旦死机,错误就更难找了,这个检测虽然很土,但很体贴,也很有效。