RacerX: Effective, Static Detection of Race Conditions and Deadlocks调研笔记
作者:Dawson Engler and Ken Ashcraft
RacerX介绍:
这是一种静态工具,它使用流敏感的过程间分析来检测竞争条件和死锁。它可以有效地推断检查信息,例如哪些锁保护哪些操作,哪些代码上下文是多线程的,以及哪些共享访问是危险的。它可以跟踪一组代码的特征,用于将错误从最严重到最不严重排序。它使用新技术来应对分析错误产生的影响——例如,通过选择最值得相信的路径,以多种方式交叉检查推断,并推断哪些信号量用于互斥而不是单方面同步.该工具速度很快,只需要 2-14 分钟来分析1.8百万行代码的系统
RacerX涉及的五个阶段:(其中第一阶段和第五阶段是用户做的,二三四是RacerX工作的阶段)
(1) retargeting it to system-specific lock-ing functions,
(2) extracting a control flow graph from the checked system,
(3) running the deadlock and race checkers over this flow graph,
(4) post-processing and ranking the results,
(5) inspection.
用户提供一张函数表,用来记录设置和释放锁以及开关中断的函数。每个函数都附带一组属性,表示他们锁的类型(spin,block,try_lock,recursive,semaphore,read/write),通过这些属性,RacerX来确定取得锁和释放锁后效果。
用户也可以提供一个annotator routine,用来标记程序是单线程,多线程或者中断处理程序。数据竞争检测器根据这些注释来判断访问这些历程是否需要加锁以及加什么锁。
总体来说,RacerX产生的注释规模不大,几百万行代码注释小于100行,
第一个阶段,遍历系统中的所有文件,提取存储在文件中的控制流图(CFG)为了支持流敏感分析,每个语句将带上一组指针,用来指向它的后继。
第二个阶段,这个阶段将分析整个系统的CFG,遍历之后检查死锁或者数据竞争,(CFG中可能存在多个root,因为有些函数没有callers,例如操作系统中的系统调用),给定一组root,分析阶段将对每个root进行迭代遍历,对CFG进行流敏感分析,深度优先遍历,过程间遍历,以及跟踪任意点持有的锁集,检查每个语句时,检测器都会传递当前语句的锁集和其他信息,为了降低复杂度,使用缓存技术(缓存使用相同锁集到达的CFG)
最后一个阶段:对分析结果进行后置处理,计算错误信息的rank,然后将这些信息展现给用户进行手动检测,rank基于一下两种规则:
1,误报的可能性,2检查的难度(排名所花费开销加大,大于分析的开销)
RacerX结果验证:
检测了三个系统Linux(2.5.62),FreeBSD(5.1),SystemX(一个更加普遍的大型商用操作系统)
对于SystemX,使用RacerX中的free checks 和lock checks进行检测,free checks中的错误率为0.25%(4 in 1600),lock checks错误率为0.4%(2 in 500)。
对于Linux分别为0.3%和0.46%
对于静态分析检测,在大型未知的系统中,要检测出非法访问(数据竞争)是否真的发生了,是非常困难的,需要对代码不变量和实际的代码交互进行推理,而这两者往往都不会进行记录,因此一个单一的竞争条件报告往往需要几十分钟进行诊断,并且最后也不一定能确认是否真的发生了错误。