【Research】MagicFuzzer: Scalable deadlock detection for large-scale applications
2012-ICSE |MagicFuzzer: Scalable deadlock detection for large-scale applications | Keywords:deadlock detection;multithreaded programs;Static;Graph;Offline
文章目录
- 2012-ICSE |MagicFuzzer: Scalable deadlock detection for large-scale applications | Keywords:deadlock detection;multithreaded programs;Static;Graph;Offline
- Research Problem
- Research Gap
- Research Challenges
- Methodology
- Contributions
- Experiment Results
Research Problem
主要关注在大规模程序数据集中检测资源型死锁
Research Gap
当前潜在死锁检测方式包括静态分析、模型检测、动态分析、运行时监控 或者组合使用
其特点在于:
静态检测与模型检测对整个程序全面分析
动态监测在精度与可扩展性方面具备优势 可判断潜在死锁是否真实存在,但是无法有效排除误报
基于模式的死锁 精度低 易误报 性能下降
现代死锁检测技术 如MulticoreSDK Deadlock Fuzzer 通常先预测 基于锁集 lockset 定位潜在死锁。检测到潜在风险 进一步确认或修复 btw 如果运行过程中直接覆盖不到相关执行路径 产生误报
对于大规模应用程序 规模庞大 在一次执行中恰好触发某一特定死锁概率低 导致动态死锁检测在覆盖率与触发条件方面重大挑战
具体表现为:

传统方法就是构建这种锁依赖图。图中线程t1 持有锁l1 请求锁l2 线程t2 持有锁l2 请求锁l1。形成环路 视为潜在死锁。在ITCAM应用中,锁顺序图包含超过30万个节点与60万条边,
Goodlock在检测时需耗费约48小时及13.6GB内存,效率极低。
所以
MulticoreSDK:位置分组两阶段检测 目的降低图规模;无法剔除不可能参与循环的冗余锁
DeadlockFuzzer:动态分析 在程序执行过程记录所有锁依赖关系 全排列搜索结合启发式剪枝,需在完整的锁依赖集上进行搜索,内存消耗极大,且确认阶段仅针对单个循环进行主动调度,导致命中真实死锁的概率较低。
Research Challenges
- 如何有效剪枝,最大化程序的降低这个锁依赖图的规模
- 如何避免检测同一环的多个排列
- 如何提高真实死锁确认的命中率
Methodology
三个阶段
-
P1: 执行轨迹生成
输入:程序p
处理:监控关键事件 比如线程create、事件acquire、release;小技巧:为每个锁m维护一个计数器,避免同一线程多次获取同一锁 只有acquire和release在该线程执行结束存在差值 才会记录
输出:包含锁依赖关系的日志 D
-
P2: 锁顺序图剪枝与循环检测
输入:D
处理:使用Magiclock算法,核心思想:只有锁节点同时有入边和出边才有可能构成锁循环,所以可以删除仅有一个或者一个都没有的,但是删除之后会产生新的不符合条件的节点,所以需要迭代删除,直到均为符合节点
此外线程特异性:每个线程在一个循环中最多出现一次,不同排列中线程的相对顺序 可以根据环中最小线程id作为先导,DFS搜索剪枝重复线程
实现方案:不需要显示保留图结构 而是利用每个节点的度数进行判断
- 构建初始图度数
- 迭代度数剪枝 从而得到cycle_set
- 基于线程特异性利用DFS 进一步剪枝 cyclic_set 剪为 CycleSet
输出:CycleSet候选死锁集合
-
P3: 死锁确认
输入:CycleSet
实现:
- 对象抽象:将CycleSet中的锁映射到实际执行中的锁对象
- MagicFuzzer调度器:目标 主动触发CycleSet,因为多线程程序运行时线程顺序和锁获取顺序不确定,这里不是没有依据的进行fuzzing了,而是带着答案去验证是否正确,如果不控制线程调度 可能一些潜在循环永远无法触发实际死锁
- CheckDeadlock(t, ToAcquire(t), Lockset(t)) 判断是否会形成死锁
- CheckAndPause:检查上面的三元组是否在CycleSet里面,如果匹配,把t线程暂停,确保其他线程有机会执行,从而触发整个死锁循环
输出:MagicFuzzer接收CycleSet作为输入(Fuzz的seed?感觉有点像 不是的 不会变异) 在单次执行中主动调度线程,尝试触发实际死锁
Contributions
主要三个贡献:
- 提出新的Magiclock算法 最大化有效剪枝 降低开销,助力程序执行过程高效检测死锁循环
- 提出新的主动线程调度策略,可基于CycleSet进行并行调度,提高死锁触发概率
- 实现基于C++的工具,在大型C/C++程序上验证高效性与低内存开销
Experiment Results
-
Benchmarks:
widely-used C/C++ open source programs, including SQLite [22], MySQL [16], Firefox [6], Chromium [4], Thunderbird [24], and Open Office [19].
这里的sqlite用了harness测试

-
内存和时间开销 & 真实死锁检测结果
其实在这些测试集中,检测到的真实死锁非常少,明确的只有两个,所以虽然不会误报,但是能否保证没有漏报有待商榷,毕竟剪枝的力度比对比方法大很多

-
锁依赖数量对比:

Firefox上的显著差距, Magiclock仅产生26个锁依赖,而iGoodlock产生202,408个(减少约7800倍) -
图剪枝效果:

