RFC-0053:Epitaphs

RFC-0053:墓誌銘文
狀態已接受
區域
  • FIDL
說明

這項提案的目標是讓伺服器在關閉連線前傳送訊息,指出關閉連線的原因。

作者
提交日期 (年-月-日)2018-07-19
審查日期 (年-月-日)2018-10-04

「Here lies your server」

摘要

這項提案的目標是讓伺服器在關閉連線前傳送訊息,指出為何要關閉連線。雖然規格中包含墓誌銘,但尚未實作。

提振精神

目前,伺服器沒有標準方式可向用戶端傳達為何關閉連線。這會導致開發人員必須負責確保錯誤處理作業。開發人員可以預測這類情況,並在訊息中加入特殊錯誤處理機制,或是直接忽略錯誤處理 (並冒著無法診斷錯誤的風險)。

其中一個用途是用於錯誤大多為致命的伺服器,當發生錯誤時,所有與用戶端的連線都會關閉。在這種情況下,開發人員需要通用的錯誤回報機制,因為所有對方法的有效呼叫都會因相同錯誤而終止。為每個方法宣告潛在錯誤的做法會很麻煩且不方便。

這個 FTP 的目標並非提供完整的錯誤回報機制。具體來說,無法向連線另一端傳達大量詳細資料 (包括詳細訊息、處理狀態或傳播原因)。

這個 FTP 也不會定義一組常見的錯誤代碼。

設計

此提案會修改線路格式、來源語言和第一類語言繫結。

線路格式

目前的線路格式規格包含 Epitaph 相關章節。這個部分將修訂為以下內容:

Epitaph (Control Message Ordinal 0xFFFFFFFF)

An epitaph is a message with ordinal **0xFFFFFFFF**.  A server may send an
epitaph as the last message prior to closing the connection, to provide an
indication of why the connection is being closed.  No further messages may be
sent through the channel after the epitaph.  Epitaphs are not sent from clients
to servers.

When a client receives an epitaph message, it can assume that it has received
the last message, and the channel is about to be closed. The contents of the
epitaph message explain the disposition of the channel.

The epitaph contains an error status.  The error status of the epitaph is stored
in the reserved uint32 of the message header.  The reserved word is treated as
being of type **zx_status_t**: negative numbers are reserved for system error
codes, positive numbers are reserved for application error codes, and ZX_OK is
used to indicate normal connection closure.  The message is otherwise empty.

原文語言

原文語言規範目前有一個關於墓誌銘的部分。我們會適當更新。

一流的語言繫結

實作項目應考量到,如果傳送 Epitaph 訊息,則應為關閉前傳送的最後一則訊息,且考量到錯誤在不同語言中處理方式不同 (例如,在 C/C++ 中傳送錯誤代碼、在 Rust 中傳送 Result<t, e="">,以及在 Dart 中傳送例外狀況)。</t,>

我們會在 C 繫結中新增 fidl_epitaph_write(管道, zx_status_t) 方法,以及 fidl_epitaph_t 類型。

我們會在 Raw Bindings 的部分,將下列文件新增至 C 繫結:

fidl_epitaph_write

Declared in lib/fidl/epitaph.h, defined in epitaph.c.

This function sends an epitaph with the given error number down the given
channel.  An epitaph is a special message, with ordinal 0xFFFFFFFF, which
contains an error code.  The epitaph must be the last thing sent down the
channel before it is closed.

C 變更的 CL:https://fuchsia-review.googlesource.com/c/zircon/+/178250

我們會變更 C++ 繫結,以便執行以下操作:

收到 Epitaph 後,fidl::Binding 會立即關閉管道。

開發人員可以使用 fidl::Binding::Close 關閉管道

錯誤代碼會使用 set_error_handler() 傳播至由用戶端設定的錯誤處理常式。我們會新增一個 error_handler 變化版本,該版本會使用封閉式,該封閉式會使用代表錯誤代碼的 int 變數,並移除現有的封閉式。未來可能會提供「合理的預設值」錯誤處理程序,但目前尚不清楚這會是什麼。

任何來自此管道的待讀資料都會傳回 ZX_ERR_PEER_CLOSED

C++ 繫結的 CL:https://fuchsia-review.googlesource.com/c/garnet/+/177939

其他繫結也需要更新,包括 Dart、Rust 和 Go。

說明文件和範例

我們會按照上一節所述更新說明文件。

開發人員指南

附註的目的,是讓伺服器能向用戶端提供可採取行動的資訊,說明管道和可能正在處理的要求。

本節說明 Epitaph 的預期行為和用途。

  1. 附錄訊息只會從伺服器傳送至用戶端,不會反過來傳送。如果傳送,則必須是伺服器在關閉管道端點之前,傳送給用戶端的最後一則訊息。

  2. 當用戶端收到「epitaph」訊息時,必須立即關閉管道的端點。不得嘗試讀取可能由不相容的伺服器實作傳送的管道中其他訊息。

  3. 當用戶端發現對等端已關閉,但未收到結尾文字時,就必須繼續進行,就好像已收到 ZX_ERR_PEER_CLOSED 結尾文字一樣;這兩種狀態在語意上是等同的。

  4. 當管道關閉是通訊協定達到指定成功結束狀態的預期副作用時,伺服器應傳送 ZX_OK 碑文。

    a. 範例:當用戶端在代表個別資料庫交易的介面上呼叫 Commit() 時,伺服器應嘗試套用要求的變更。如果成功,伺服器必須在關閉管道的端點之前傳送 ZX_OK 碑文。用戶可以合理推斷,ZX_OK 碑文表示交易已成功提交。

    b. 反例:許多通訊協定並未指定成功結束狀態;用戶端預期能夠連線至伺服器,並發出無限數量的請求,而不會觀察到對等端關閉,直到用戶端關閉管道的自身端為止。在這些情況下,伺服器關閉管道的端點會構成不正常的結束狀態,因此伺服器絕不應傳送 ZX_OK 輓銘。

  5. 除了通訊協定達到指定的成功結束狀態以外,伺服器可能會在關閉管道的端點前傳送非 ZX_OK 的結尾訊息。我們建議採用下列慣例:

    a. 如果伺服器因用戶端傳送格式錯誤的 FIDL 訊息而關閉連線,則應傳送 ZX_ERR_INVALID_ARGS 碑文。

    b. 如果伺服器因用戶端傳送的目前狀態無效要求而關閉連線,則應傳送 ZX_ERR_BAD_STATE 碑文。

    c. 如果用戶端嘗試透過服務探索機制連線至伺服器時,伺服器無法連線 (例如無法啟動),則此機制應傳送 ZX_ERR_UNAVAILABLE 紀念碑。(另請參閱這份草圖)。

    d. 如果伺服器無法繼續提供通訊協定,但原因並非用戶端執行的動作 (例如關閉或記憶體不足),則不必傳送任何結尾訊息。如上所述,用戶端會將此視為 ZX_ERR_PEER_CLOSED

    e. 如果伺服器遇到應用程式專屬錯誤,應傳送應用程式定義的錯誤代碼。舉例來說,如果伺服器控制了檔案系統,而使用者嘗試執行不允許的寫入作業,則伺服器可能會關閉連線並顯示錯誤。

    f. 請注意,這份清單僅列舉部分內容。伺服器可能會視情況傳送其他錯誤。如往常,建議 FIDL 作者明確記錄其通訊協定可能傳回的錯誤,包括碑文。

回溯相容性

FIDL 說明文件目前指出 0x80000001 是碑文的序數。我們將其變更為 0xFFFFFFFF,因為 0x80000001 已由 IO 使用。目前沒有任何內容會使用 0x80000001 的 Epitaph。否則,就沒有回溯相容性問題。

成效

不適用

安全性

不適用。

測試

這項功能的單元測試會新增至適當的 FIDL 繫結。每個支援的 FIDL 繫結都獲得支援後,我們應該擴充FIDL 相容性測試的組合。

缺點、替代方案和未知事項

我們考慮製作一個包含 Epitaph 事件的 System 介面,這會是所有其他介面訊息的父項。墓誌銘文本身並未保證如此重大的變更。目前也存在兩個實作障礙。首先,衍生類型目前無法運作,但這項功能應該很快就會變更。接著,由於此提案會變更執行階段,而 FIDL 剖析器 / 產生器會依賴執行階段,因此引入系統訊息並嘗試在執行階段中使用該訊息,會導致循環依附。

這項 FTP 所造成的 API 變更,不會導致 Epitaph 支援功能無法在日後的系統訊息中運作。

我們曾提出將某些碑文處理機制納入原始語言的想法,讓 zx_status 標記可對應為 FIDL 定義的列舉。這項功能會在日後的更新中推出。

建議的實作方式會造成競態狀態。如果一個執行緒同時寫入訊息,而另一個執行緒關閉管道,則紀念碑可能會在其他執行緒的訊息之前,但在呼叫 zx_handle_close() 之前寫入。替代做法包括鎖定管道或提供明確的系統呼叫。我們將從執行緒不安全的版本著手,進一步瞭解問題空間。