RFC-0053:Epitaphs

RFC-0053:Epitaph
狀態已接受
區域
  • FIDL
說明

本提案的目標是允許伺服器在關閉連線前傳送訊息,指出連線中斷的原因。

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

「你的伺服器」

摘要

本提案的目標是允許伺服器在關閉連線前傳送訊息,會指出連線關閉的原因。雖然Epitaph 已包含在規格中,但還沒有實作。

提振精神

目前,伺服器並沒有標準的方式可以與用戶端通訊,因此連線已關閉。這會影響確保錯誤處理的責任對開發人員造成影響。開發人員可以預見這種情況,並在訊息中建構特殊的錯誤處理機制,或直接忽略錯誤處理機制 (以及無法診斷的錯誤的風險)。

其中一種用途是發生錯誤的伺服器數量多到少,而當發生錯誤時,所有用戶端連線均已關閉。在這種情況下,開發人員會想採用一般用途的錯誤回報機制,因為對方法的所有有效呼叫都會因同樣的錯誤而終止。要為每個方法宣告潛在錯誤的替代方案,相當麻煩且尷尬。

這個 FTP 的目標是提供廣泛的錯誤回報機制。具體來說,能夠將大量詳細資料 (包括詳細訊息、程序狀態或傳播原因) 傳送到連線的另一端的功能不在範圍內。

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

設計

本提案會修改傳輸格式、來源語言和第一個類別語言繫結。

電匯格式

傳輸格式規格目前有 Epitaphs 區段的內容。本節修訂如下:

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.

原文語言

原文語言規格目前有 Epitaphs 章節。便會視情況更新。

第一類語言繫結

實作作業應考量以下情況:如果 Epitaph 訊息已送出,則應該是關閉前的最後一則訊息,以及不同語言中的錯誤處理方式不同 (例如透過 C/C++ 傳送錯誤代碼、Result<t、e=""> 在 Rust 中傳送,以及 Dart 中的例外狀況)。</t,>

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

我們會將下列文件新增至 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》變更:https://fuchsia-review.googlesource.com/c/zircon/+/178250

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

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

開發人員可以使用 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。

說明文件與範例

說明文件將於上一節的說明更新。

開發人員指南

淘汰的用意是讓伺服器將管道處理方式和可能處於傳輸中要求的相關實用資訊提供給用戶端。

本章節會說明 API 的預期行為和使用方式。

  1. 劇集只會從伺服器傳送至用戶端,絕對不會從其他方向傳送。如果已傳送,則必須在伺服器關閉管道結束之前,伺服器向用戶端傳送最後一則訊息。

  2. 用戶端收到簡短訊息時,必須立即關閉管道的結尾。如果有錯誤伺服器實作這類情形,應用程式不得嘗試讀取來自該管道的後續訊息。

  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 作者應清楚記錄通訊協定可能傳回的錯誤,包括 Epitaph。

回溯相容性

FIDL 說明文件目前指出 0x80000001 是劇集的序數。我們將其變更為 0xFFFFFFFF,因為 IO 正在使用 0x80000001。目前沒有任何仰賴 Epitaphs 的 0x80000001。否則就不會有回溯相容性問題。

效能

不適用

安全性

不適用。

測試

系統會將這項功能的單元測試新增至適當的 FIDL 繫結。在每個支援的 FIDL 繫結獲得支援後,我們應增強 FIDL 相容性測試組合。

缺點、替代方案和未知

我們考慮設計一個包含 Epitaph 事件的 System 介面,也就是所有其他介面訊息的父項。Epitaph 本身不一定是大規模的改變目前也有兩種實作障礙。首先,衍生類型目前無法正常運作 但應該很快就會變更接著,由於本提案會變更執行階段,而 FIDL 剖析器 / 產生器都依附於執行階段,因此導入系統訊息並嘗試在執行階段中使用,會導致循環依附元件。

此 FTP 產生的 API 變更不會阻止 Epitaph 支援移至日後的系統訊息。

某個概念是將一些神經處理機制融入原文語言中,允許將 zx_status 標記對應至 FIDL 定義的列舉。這會延後到未來的工作時間。

建議的實作方式為兒童不宜。如果其中一個執行緒同時寫入訊息與關閉管道的另一個執行緒,則可能會在呼叫 zx_handle_close() 之前,先寫入另一個執行緒的訊息之前。替代方案包括鎖定管道或提供明確的系統呼叫。我們先從執行緒不安全的版本著手,以便進一步理解問題空間。