RFC-0057:預設沒有控制代碼

RFC-0057:預設無控制代碼
狀態已接受
領域
  • FIDL
說明

我們建議預設在 FIDL 類型宣告中禁止使用控制代碼,並新增關鍵字資源,以標記可包含控點或其他資源類型的類型。新增或移除資源修飾符可能會破壞來源。

作者
提交日期 (年-月-日)2020-01-16
審查日期 (年-月-日)2020-01-23

「看著男子,別擔心!」

摘要

我們建議預設在 FIDL 類型宣告中禁止控制代碼,並新增 新關鍵字 resource1,用於標記可包含帳號代碼或 和其他資源類型新增或移除 resource 修飾符可以是 破壞原始碼。

提振精神

FIDL 的一項獨特功能,就是支援 Zircon 帳號代碼。帳號代碼是 32 位元的整數 但會特別處理:必須移動而非複製 為了避免資源外洩這位特別治療主管 處理哪些功能僅適用於純文字資料 使用任意帳號雖然 FIDL 繫結「可以」根據 出現控點,但這樣做是不理想的做法,因為這樣會破壞發展能力 保證。例如,在資料表中新增欄位通常安全無虞,但 帳號代碼欄位不僅會破壞原始碼,還包括所有資料表 這些型別的隱含狀態這會讓繫結保持較為保守 一律假設類型可能包含控制代碼,即使程式庫作者 無意新增

應對措施導致入侵:

  • 在 Dart 中,導入 FIDL 到 JSON 編碼的努力收到了婉拒訊息 這只會處理無控點的類型,進而損害變化。這項服務 最終是使用 MaxHandles 屬性建構,但這是 這項暫時性解決方案僅適用於最外層的類型 這些類型無法相互連線
  • 在 Rust 中,首次為型別新增控制代碼是破壞原始碼 因為類型不會再衍生 Clone 特徵。(正確複製 處理常式需要叫用 zx_handle_duplicate syscall、 否則可能會失敗)。
  • 通訊協定的 Rust 繫結會透過可變動參照採用 FIDL 物件, 而不是明確接受擁有權,這樣物件 之後可重複使用

我們能夠以更安全的方式處理這些案件 程式庫的作者,用於指出類型是否可能包含帳號代碼,以及是否變更 這些跡象表明 似乎會破壞原始碼

設計

術語

FIDL 類型可以是「值」類型或「資源」類型。資源類型 包括:

  • handlehandle<H>,其中H 是帳號代碼子類型
  • Prequest<P>位置 P 是通訊協定的名稱
  • 使用 resource 修飾符宣告的結構體、資料表或聯集
  • 參照某種資源類型的類型別名
  • 包裝資源類型的新類型 RFC-0052
  • T?,其中 T 為不可為空值 資源類型
  • array<T>vector<T>位置 T 是資源類型

所有其他類型都是值類型。

正確使用 resource 修飾符時,值類型一律不會包含 會處理,但資源類型可能會 (現在或未來) 包含控點。

語言

新的修飾符 resource 可套用至結構、資料表和聯集 宣告的內容

如果沒有 resource,宣告就無法包含資源類型。 FIDL 編譯器必須驗證這一點。它只需要檢查直接欄位:如果 A 包含 B,兩者都未標示為資源,B 包含控制代碼, 編譯作業會因為 B 而失敗,且不需要發生個別錯誤 關於 A 的說明文字,當中包含控點。

如果使用 resource,宣告可以包含資源類型。而 所宣告的型別即使不包含 再複習一下,機構節點 是所有 Google Cloud Platform 資源的根節點

原則上,語言允許對新類型宣告使用 resource RFC-0052。不過,這並沒有實際的使用方式 包裝值類型,因此新類型會以隱含方式繼承值/資源 以及其對應的類型狀態

文法

此提案修改了 FIDL 文法中的 1 項規則:

declaration-modifiers = "strict" | "resource" ;

JSON IR

這項提案會將包含布林值的鍵 "resource" 加入 "struct_declarations""table_declarations""union_declarations" 陣列。

請注意,"max_handles" 沒有多餘的金鑰。值類型必須包含 max_handles 設為零,但資源類型可以有任意數量的 max_handles,因為此參數會反映宣告的實際內容 程式庫作者的意圖以允許控制)。

繫結

本提案不提供繫結的具體變更。不過 讓 FIDL 繫結作者 (包括 FIDL 團隊) 能夠解決問題 相關說明請參閱動機。以下列舉幾個例子 但不接受:

  • 對值型別 (或更多) 實作 JSON 序列化和序列化作業 可能是 FIDL 文字格式,而非 JSON,如 RFC-0058
  • 針對值/資源,針對 C++ Clone() 方法使用不同的類型簽章 強調只有資源複製作業可能會失敗
  • 將 Rust 通訊協定接受值類型引數做為 &T 和資源類型 做為 T 的引數,而非同時使用 &mut T 和僅透過 資源類型

API 評分量表

API 評分量表應為您提供使用 resource 的時機。有些簡單 案件:

  • 沒有資源類型的結構不應標示為 resource,因為 結構體的設計無法擴充 (在多數情況下, 無法支援 ABI)。
  • 不含資源類型的嚴格資料表或聯集 resource,因為嚴格程度已信號會修改欄位 是一項破壞原始碼

並處理未運用彈性資料表和聯集的情況 一開始都有一個帳號代碼例如,我們可能會建議 另一個選項則取決於程式庫的用途 如所用語言 以及其他因素

執行策略

高階導入步驟包括:

  • 剖析 fidlc 中的 resource 關鍵字。
  • 遷移現有的 FIDL 程式庫以使用 resource (詳情請參閱 不明
  • 透過測試驗證 fidlc 中的值/資源類型規則。
  • resource 旗標儲存在 JSON IR 中,並以 fidlgen 公開。

人體工學

這個提案引進了新的概念,使得 FIDL 變得更加複雜。取消喜歡 其他 FIDL 結構,例如「struct」通訊協定和通訊協定新使用者則不會 猜猜什麼「資源」這代表他們必須從說明文件中學習

此提案是否可區別 FIDL 的語言 符合人體工學具體做法是將注意力放在含有控點的宣告上 特別是當實際的帳號代碼值隱藏在巢狀結構中時更是如此。所有人 瀏覽程式庫時,會立即看到結構有控點,而不是 只有資料另一方面,您可能比較不會擔心人體工學 是否使用 resource 及輸入關鍵字。將一個宣告從 都可能產生痛苦的串聯效果,因此許多型別都必須 成為資源 (但這是好事,因為它可以 會顯示為來源中斷)。

FIDL 繫結改善後會提高複雜度。使用 可以自由為值類型和資源類型、繫結提供不同的 API 也能提升安全性、符合人體工學如需這些改善項目的例子,請參閱 繫結

說明文件和範例

您必須完成以下工作:

  • 更新所有涉及帳號代碼的說明文件,並視情況更新使用 resource
  • 更新 FIDL 語言規格,以說明 resource 修飾符。
  • 在 FIDL 教學課程中提及 resource。這裡要有一個簡短音 說明所有修飾符 (例如 strictresource)。
  • 提供指引,說明沒有帳號代碼的新類型是否應為資源。
  • 繫結利用值/資源區別後,請更新 查看不同值類型提供的 API 之間的差異 和資源類型,並提供在這兩種類型之間進行轉換的操作說明 (如果可以的話)。

回溯相容性

本提案不會影響 ABI 相容性。

修訂條款 (2021 年 7 月)。在實作期間,我們發現 本提案和 RFC-0033:處理不明欄位的方式 嚴格程度。某些繫結會在解碼時儲存不明成員 資料表和彈性聯集;如果 未知的成員包含控制代碼,因此在這個情況下,解碼必須失敗。詳情請參閱 相容性指南

修訂條款 (2021 年 10 月)。RFC-0137 之後:捨棄位於 FIDL,繫結不會再儲存未知資料,因此也沒有 極端案件因此,值/資源區別不會影響 ABI 相容性。

新增或移除 resource 修飾符都不能與原始碼相容 可轉換2RFC-0024。 繫結已明確允許產生兩種類型的不相容 API 只有在修飾符出現差異時,系統實際上 就無法編寫程式碼,在新增/移除移除/移除程式碼前後 修飾符圖書館作者希望轉換至 resource 與來源相容的方式必須建立新的類型和方法,而不是變更 現有目標對象

繫結作者開始利用值/資源區別後, 就會重新審視這項決定因此您可能需要 可精簡路徑 (可能使用附有 [Transitional] 屬性)。一開始,我們並不清楚這句話是否太過不清楚 限制、低劣 API 改善措施、 。

成效

本提案對建構效能產生輕微的影響:FIDL 編譯器會 多做一些工作來剖析新關鍵字並驗證其用途。沒有任何 對 IPC 效能的直接影響因此若某些特徵 語言,前提是繫結會使用值/資源區別機制來建立 API 以免不必要的副本。舉例來說,您不需要在 值類型物件來多次傳送

安全性

此提案不會直接影響安全性,但允許繫結 提供更安全的 API舉例來說,針對以下項目,C++ 可能會在 Clone() 上強制執行錯誤處理: 具有 [[nodiscard]] 的資源類型,Rust 可以採用資源類型方法 。 這類異動可能避免發生錯誤 (包括安全性錯誤)。

測試

系統將以下列方式測試這項功能:

  • 針對剖析和驗證程式碼路徑,在 fidlc 中新增測試。這些測試 應在各種情況下,當宣告標示為 resource (或 不符合資源類型 (或值類型) 的定義。
  • 除了修正以外,請為黃金部分新增部分資源類型宣告 需要 resource 的現有宣告。
  • 將 fidl 變更測試套件更新為 示範從值類型轉換到資源類型 反之亦然

缺點、替代方案與不明

這項提案導入了一個新的關鍵字,使語言更加複雜。 關鍵字數量過多可能造成問題「嚴格資源聯集」略為 並引發麻煩

本提案以下列兩種方式降低 FIDL 的改善能力保證:

  • 在此之前,在型別中新增帳號代碼應該不會造成來源中斷 變更。現在,我們已明確允許並預期這個值 (除非型別是 已在預期需要新增控制代碼時標示 resource)。
  • 在此之前,您可以針對未來 (1) 加上 也可 (2) 可以在任何其他部分 類型。現在,圖書館作者必須在一開始時選擇 (1) 和 (2) 選項。

這項提案有兩個主要替代方案:

  • 不採取任何行動。可在任何地方使用帳號,並配合現實 新增或移除時,繫結必須維持來源相容性 控制代碼
  • 預設允許帳號代碼。如同這個提案,但假設聲明 預設會搭配使用資源類型,而且規定 value 關鍵字必須設為禁止 宣告中的資源類型

動機」與「倫理學」部分的定義為 什麼也不必做什麼至於另一項替代選項,經驗顯示 郵件不含帳號,而且在通訊協定中傳遞帳號代碼時, 並預先規劃換句話說,值類型是常見情況 之後新增帳號代碼的功能可能不如 似乎。這表示建議不允許使用帳號代碼,是更好的預設值。

本提案主要為使用 FIDL 繫結的開發人員帶來許多好處, 缺點適用於設計 API 的程式庫作者。這項權衡利弊 有關 Fuchsia API Council Charter 的後續部分。 優先考量的是開發人員,而非 API 設計人員和實作者。

我們已建議另一個替代方案:做為參照處理。而不是 值類型禁用控制代碼便會解決值/資源問題, 將帳號代碼做為參照項目表示複製含有帳號代碼的結構 只會對相同的帳號代碼發出另一個參照這可以 在 C++ 中使用 shared_ptr,而且不必耗費太多心力,就能大幅簡化作業 新增「resource」關鍵字。然而,它還存在以下挑戰:

  • 所有繫結都必須採用記帳機制,確保帳號代碼 等到最後的參考資料消失時,我們才會予以結案。這個設計在某些情況下 語言。
  • 將帳號代碼傳送至其他程序後,這個帳號的所有其他參照會 就會變成無效狀態,例如閃爍指標。處理帳號代碼時不費吹灰之力 一般價值較高的問題表示我們在這些領域 情境。
  • 由於過程中會變更所有帳號代碼的類型, 所有語言的破壞性變更如要順利轉換,就需要投入大量心力 這些研究有助於我們找出 能引導後續作業的標準

本提案仍有幾個待解決的問題:

  • 我們該如何遷移現有的 FIDL 程式庫?將所有現有項目標示為 使用 resource 宣告很安全,但不會反映程式庫作者 意圖。僅標示最低限度 (例如包含帳號代碼的類型) 效果可能,但假設沒有 帳號代碼不應包含任何
  • 採用一般資料類型之後,這項功能如何與一般資料類型互動? 舉例來說,如果定義 Pair<A, B> 類型,邏輯應該是 如果 AB 是資源類型 並加註 Pair 本身有其他較適合 推算類型是否為資源?

既有作品和參考資料

本提案旨在確保 變更型別的值/資源狀態。 RFC-0024 與此做法相關 ,因為該機構確立了 FIDL 的來源相容性標準。此外, 碰觸帳號代碼的問題,導致不容易在Clone 這個提案能解決的 Rust。

我們不清楚其他能夠處理這個問題的其他處理序間通訊 (IPC) 系統 (區分可能含有帳號代碼或系統資源的類型)。不過 以「感染」的方式為型別加註所有使用網站都是 程式語言。例如,使用 JavaScript、Python 編寫的非同步函式 Rust 則採用這種行為,以及 Haskell 中的 IO monad。


  1. 此提案的較舊版本,稱為關鍵字 entity

  2. 此提案的先前版本需要變更: 可轉換。