| RFC-0178:每項工作有多個偵錯例外狀況通道 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | Zircon 允許工作有多個偵錯例外狀況通道。 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2022-06-08 |
| 審查日期 (年-月-日) | 2022-07-12 |
摘要
這項 RFC 建議變更 zx_task_create_exception_channel,允許在一個工作中建立最多 32 個偵錯例外狀況通道。
提振精神
Fuchsia 的偵錯工具需要建立作業的偵錯例外狀況管道,才能監控程序啟動,以便擷取感興趣的程序並積極附加至該程序。偵錯例外狀況管道通常是在系統的根工作中建立,方便偵錯工具監控所有程序。
程序啟動時,核心會遍歷工作階層,尋找要通知的偵錯工作例外狀況管道。這項逐步追蹤作業會從新程序所含的工作開始,並向上追溯階層,直到找到偵錯工作例外狀況管道或到達根工作為止。
不過,目前的實作方式有兩個缺點。
- 針對特定工作,最多只能有一個偵錯例外狀況管道,也就是說,最多只能有一個偵錯工具監控工作階層的任何子樹狀結構。
- 系統只會通知第一個找到的偵錯例外狀況管道,也就是子項工作上的偵錯工具會阻止父項工作上的偵錯工具觀察程序啟動。
利害關係人
講師:cpu@google.com
審查者:brettw@google.com、maniscalco@google.com
諮詢對象:johngro@google.com
社會化:這個想法已在 Fuchsia 的 Kernel Evolution Working Group 中討論。
設計
我們建議 Zircon 允許一個工作有多個偵錯工作例外狀況管道。
Zircon 中有 5 種例外狀況通道:
debug 工作、工作、debug process、process 和執行緒。 每個物件最多只能建立一次。這項限制是為了避免發生棘手情況,例如多個例外狀況處理常式為 ZX_PROP_EXCEPTION_STATE 設定不同的值。
不過,這裡的「debug 工作」很特別,因為這是僅限通知的管道,唯一可接收的例外狀況類型是 ZX_EXCP_PROCESS_STARTING,其中 ZX_PROP_EXCEPTION_STATE 會遭到忽略。因此,您可以在一個工作中允許多個偵錯例外狀況通道,不必擔心不一致的問題。
如果一個工作建立多個偵錯工作例外狀況管道,系統會依序將 ZX_EXCP_PROCESS_STARTING 事件傳送至所有管道,讓多個監聽器檢查程序。只有一個偵錯工具可附加至特定程序,這項限制不會改變,因為「debug process」例外狀況管道仍由單一偵錯工具擁有,且第一個以外的所有偵錯工具都會收到 ZX_ERR_ALREADY_BOUND。
此外,我們也建議修改 ZX_EXCP_PROCESS_STARTING 事件的事件傳播,即使在子項工作上建立例外狀況管道,一個事件也會一路傳播至根層級。系統會先通知工作階層中較低層級的偵錯工作例外狀況管道,再通知較高層級的管道。在任何指定層級,系統會先通知較早建立的管道,再通知較晚建立的管道。只有在通知所有例外狀況管道並關閉例外狀況物件後,程序才能繼續。
請注意,任何例外狀況訊息接收器只要不關閉例外狀況物件的控制代碼,就可能無限期地保留程序啟動。不過,他們無法直接停止程序啟動。
實作
系統呼叫的 API 或 ABI 不會變更。zx_task_create_exception_channel 的現有行為將有所變更,最多可建立 N 個頻道,而非在第一個頻道建立後傳回 ZX_ERR_ALREADY_BOUND。
效能
因為可能有更多聽眾封鎖程序啟動,導致效能下降。不過,偵錯例外狀況管道不應在正式版環境中使用,也不應由長時間執行的程式保留。這項功能僅供偵錯工具或類似的偵錯工具使用,因此影響應該很小。
一般來說,偵錯工具應在執行必要設定後,立即關閉例外狀況控點。
安全性考量
為避免對核心發動 DoS 攻擊,我們應限制在單一工作中建立的偵錯工作例外狀況通道數量上限。限制應足夠大,可允許任何合理數量的偵錯工具執行,例如 32。
測試
系統會將新的測試案例新增至 //zircon/system/utest/debugger,以涵蓋這項功能。
說明文件
描述「例外狀況處理」和「zx_task_create_exception_channel」的文件將更新,以反映這項異動。
缺點、替代方案和未知事項
替代方案:程序的使用者空間委派作業會在根工作上啟動
這個方法可避免核心變更。而是由使用者空間委派項目保留根工作偵錯管道,並提供 FIDL 介面,供偵錯工具訂閱程序啟動。委派對象可以是元件管理工具本身 (目前提供 fuchsia.kernel.RootJob),也可以是獨立程式。
通訊協定看起來會像
@discoverable
protocol RootJob {
/// Hanging get pattern
GetProcessStartingEvent() -> (resource struct {
process zx.handle:PROCESS;
continue zx.handle:EVENTPAIR; // dropping this eventpair will propagate
// the event to the next listener.
}) error zx.status;
};
這種方法的問題包括
- 這項設定只適用於根工作。偵錯工具需要根工作和非根層級工作的兩種邏輯。
- 在子項工作建立的例外狀況管道可停止事件傳播至根目錄。
- 如果 FIDL API 提供的函式與系統呼叫類似,會造成混淆。
替代方案:debug_agent 支援多個用戶端
我們也可以讓 debug_agent 支援多個用戶端,解決今天的問題,也就是讓 debug_agent 成為單例。
問題如下:
- 這會增加工作量。
- debug_agent 將成為 Fuchsia 的指定偵錯工具。其他偵錯工具必須與 debug_agent 通訊,這會公開大型且不穩定的介面。