一個 Linux 核心 Bug 讓我的機器整台卡死:追查 async-profiler 的死鎖 (★
100 分)
文章主軸是作者在使用 async-profiler(JVM (Java Virtual Machine,Java 虛擬機) 常用的取樣分析器)進行效能剖析時,意外觸發 Linux 核心層級的死鎖,導致整台機器完全凍結。作者自稱「對核心很好奇」,把這次事故當成一次深入核心內部的實作練習:用 QEMU (Quick Emulator,虛擬化/模擬器) 重現問題、搭配 GDB (GNU Debugger,除錯器) 追查,並調整 ASLR (Address Space Layout Randomization,位址空間配置隨機化) 等設定來降低除錯難度,最後將問題鎖定在 perf 子系統與 hrtimer (high-resolution timer,高解析度計時器) 相關路徑,並以額外的狀態檢查避免在事件已停止(例如 `PERF_HES_STOPPED` 這類旗標)時仍持續重啟計時器而把核心卡死。
討論中不少人特別點出 async-profiler 近期加入的 heatmap(熱圖)輸出很值得關注。有人分享前一天剛看完 Andrei Pangin(async-profiler 作者)在 Devoxx 的演講,也引用 Netflix 的 Flamescope 文章,認為熱圖把火焰圖拉成「隨時間變化的剖面」,更容易看出週期性型態、偶發抖動與離群值。作者也回應自己常用熱圖做模式辨識,認為這是被低估但非常實用的功能。
Hacker News 多數高分回應肯定這篇「除錯旅程」的含金量,尤其讚賞作者願意一路往核心深處挖到能提出修補方向。同時也有人質疑:既然這類缺陷會把整台機器鎖死,為何核心測試體系沒有更強的回歸測試保護;有人建議參考既有核心測試做法,設計一個可穩定失敗的案例,甚至用 User Mode Linux (UML,使用者模式 Linux) 或 VM (Virtual Machine,虛擬機) 來跑測試並偵測「是否還能建立新行程」等活性指標,以避免問題再次回歸。
技術細節上也出現針對修補程式條件式的 C 語言優先序討論:有人擔心 `||` 與 `!=` 的解析順序會出錯、主張加括號;作者澄清 `!=` 的優先序高於 `||`,不影響語意,但也同意括號能提升可讀性,並有人補充更常見的坑其實是位元 OR 的 `|` 與比較運算混寫。另有讀者建議改用 bpftrace(基於 eBPF (extended Berkeley Packet Filter,Linux 核心追蹤機制) 的追蹤工具)直接觀察核心呼叫堆疊與回傳值,可能比 QEMU + GDB 更省力;也有人提到可用 NMI (Non-Maskable Interrupt,不可遮罩中斷) watchdog 協助抓硬鎖死。實務面則有人分享在大量 Docker 映像檔與 volume(資料卷)堆疊、同時併發啟停 20-30 個容器時,偶爾也會遇到難以重現的核心死鎖;另有人指出這很像 Minecraft 搭配 Spark profiler 外掛時曾經把系統凍結的同一類問題,整體共識是:核心規模龐大、邊角競態難免,但把追查過程寫清楚,對其他人排障與推動修補很有幫助。
👥
17 則討論、評論 💬
https://news.ycombinator.com/item?id=46280465