关闭一个线程

注意:由于个人能力及知识水平问题,以下内容可能有原则性错误,请批判着阅读!

最近搜东西,又搜到了这个关于pthread_kill的话题,相信有不少人看过这个讨论。NPTL的作者真霸道。看了几遍pthread_kill的手册,然后放心的写代码,然后得到一个core dump,相信谁都会不爽的。

但用pthread_kill(pid, 0)来检测一个线程的运行情况是一件不靠谱的行为,虽然这是非常普遍的行为:Joinable的线程完结了,还没执行pthread_join(),这个状态,pthread_kill(pid, 0)能正常识别么?规范没有说,其实很多实现都没有能够区分这两种状态吧。(1 运行中, 2 运行结束,还没join)还有一种比较不大可能发生的事情——通常,你的代码能提前发现这个问题:pid如果被重用了呢?这种时候,其实你检查的是一个全新的线程。

pthread_kill()是一个非常难用的方法,在确定你的线程能正确的处理信号之前,不能随意的向某个线程发出信号;如果你的程序不能正确处理,你的整个系统都会由于这个方法的调用而终止。出于对其的害怕,我从来没有在自己的代码里使用过它。

如果要关闭一个Server线程,其实可以为线程提供一个shutdown()方法,像所有Java程序员都会的那样;如果要立刻终止一个线程,可以用pthread_cancel(pthread_t),当然这个方法也会有风险(你不知道你要关闭的线程是不是已经终止了,你也不知道你要关闭的线程或许是一个全新的线程)。所以,pthread_cancel(pthread_t)方法需要在同步块内调用,调用前,确认 线程处于有效的状态。而线程也需要在同步块内才能改变自己的状态。

我觉得安全的做法,不论是pthread_cancel,或是pthread_kill,都需要利用同步机制,确认线程先有效,再操作。当然,很多人不这么认为,因为他们的代码从不这样写。 :)

Leave a Comment

过去和近况(三)

11月初,我把座位从公司7楼的一端搬到了另一端(我至今还没弄清楚具体的方位),就这样,从网易杭研搬到了网易邮件部。

一切都在从头开始。

我读了一遍cyrus-sasl的代码,弄清楚其逻辑及各种结构后,为它写了一个新的认证机制。测试完后,我想我短期内不会再有C/C++的活了吧。

抽空大概的浏览了ZimbraServer的代码,我们并不打算从里面借鉴什么,我只是想尽快熟悉下邮件系统到底是怎么回事。我开始写一些底层的模块,主要是存储/解析,以及抽象一些结构,用Java开发真是感觉良好。

正在集中精神开发新Server的时候,我又同时参与了一个C++项目N(目前就我1个开发人员),项目已经开始稳定,不过还有很多后续功能要开发。我记得在1个月前做过一个梦,梦见自己开始接手这个N项目,程序不稳定,服务器一直坏,压力很大。没想到前半部分成真了,后半部分是否成真,那还得看天意。

Leave a Comment

过去和近况(二)

我和同事两人干了一件有趣的事情,我们把自己的Map-Reduce/DFS系统与Hadoop,以及另外一套某搜索引擎使用的Map-Reduc/DFS做了较为深入的分析和性能/功能测试。测试的结果非常符合我们的期望,NEMR/DFS的组合从文件的存取效率,Map-Reduce的任务分发/容错/易用性等都要明显好于Hadoop与另一套系统。当然,这三个系统的定位并不一致。

四月份,我接到的任务是重新整理DFS的Java接口,除了整理了一下包结构与异常机制,我基本没有做什么有价值的事情。原有的Java代码有较深的C/C++风格,另外,代码结构虽然凌乱但能完美的工作,我有些无从下手。当把整理完的结果commit,并关掉任务的时候,我有一种深深的负罪感。

我们组与其他部门开始合作一个应用于廉价存储设备的支持大文件的分布式文件系统(大文件意味着整个系统的元数据基本很小)。支持大文件的分布式系统开发其实比较简单,这是一个C++的项目,作为一个不是很称职的Java程序员,刚开始做C++项目的时候充满了惊奇的体验。我只负责一些边缘的开发工作,比如为这个文件系统做一个shell, 并参与了部分系统对外接口的开发,做为一个C++初学者都算不上的家伙,我在这个项目里每写一行代码都十分的小心,倒也没有出什么问题。

我一直期望把分布式文件系统的接口做的不让人惊奇。处理DFS里的文件像本地文件那样open/write/read/close/unlink,支持流式写入等。(最近开始全面接手上面的项目,可以对其好好改造啦!嘿嘿)

6月份开始了一个较大的项目,我们组开始做一个全新的支持廉价设备的(且低碳省电的)大量小文件存储的分布式文件系统。我负责开发文件的对外Java接口,以及文件系统的存储节点(C++)。其他同事开发管理工具和master。由于考虑到自己只是一个C++新人,我有意识的只使用C++的一个子集来开发系统以避免额外的复杂性。虽然在一开始就约束自己不要重做轮子,可是到了最后,还是造了很多基础设施(线程安全的集合, BlockingQueue, ThreadPool, Runnable, DailyRollingLog等等),  Hacker了一个库的部分代码。可能是因为没有找到简单,可靠的C++实用库吧。这次开发感觉很顺利,我想很大程度上要归功于我们使用了一个非常酷的通信/rpc框架,它引起的麻烦远远要小于它所克服的麻烦。

之后的精力花在了大量线上数据的迁移/线上系统的维护上面,大概有10000亿个线上文件需要迁移到新开发的文件系统。

Leave a Comment