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
Socialization:這個想法是在 Fuchsia 的 Kernel Evolution Working Group 中討論過的。
設計
我們建議 Zircon 允許在單一工作中使用多個偵錯工作例外狀況管道。
Zircon 中有 5 種例外狀況管道:偵錯工作、工作、偵錯程序、程序和執行緒。每個類別最多只能在對應物件上建立一次。這項限制的設定目的,是為了避免發生棘手的情況,例如多個例外狀況處理常式為 ZX_PROP_EXCEPTION_STATE
設定不同的值。
不過,這裡的「偵錯工作」是專門用於通知的管道,因此唯一可接收的例外狀況類型是 ZX_EXCP_PROCESS_STARTING
,而 ZX_PROP_EXCEPTION_STATE
會遭到忽略。因此,您可以在單一工作中允許多個偵錯例外狀況管道,而不必擔心資料不一致。
如果在單一工作上建立多個偵錯工作例外狀況管道,系統會依序將 ZX_EXCP_PROCESS_STARTING
事件傳送至所有管道,讓多個監聽器檢查程序。只有一個偵錯工具可附加至特定程序的限制並未改變,因為「偵錯程序」例外狀況管道仍由單一使用者擁有,且除了第一個偵錯工具外,所有偵錯工具都會取得 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 通訊,這會公開大型且不穩定的介面。