| RFC-0053:墓誌銘 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 這項提案的目標是允許伺服器在關閉連線前傳送訊息,說明連線關閉的原因。 |
| 作者 | |
| 提交日期 (年-月-日) | 2018-07-19 |
| 審查日期 (年-月-日) | 2018-10-04 |
「Here lies your server」(您的伺服器位於此處)
摘要
這項提案的目標是允許伺服器在關閉連線前傳送訊息,說明連線關閉的原因。雖然規格中涵蓋墓誌銘,但目前尚未實作。
提振精神
目前伺服器沒有標準方式可向用戶端說明連線關閉的原因。因此,開發人員有責任確保錯誤處理機制正常運作。開發人員可以預見這種情況,並在訊息中加入特殊的錯誤處理機制,也可以直接忽略錯誤處理機制 (但可能會發生無法診斷的錯誤)。
其中一個用途是針對錯誤大多為嚴重錯誤的伺服器,發生這類錯誤時,系統會關閉所有用戶端連線。在這種情況下,開發人員需要一般用途的錯誤回報機制,因為所有對方法的有效呼叫都會以相同錯誤終止。為每個方法宣告潛在錯誤的替代做法會很麻煩且不自然。
這個 FTP 的目標並非提供廣泛的錯誤報告機制,具體來說,本節不討論如何向連線的另一端傳送大量詳細資料 (包括詳細訊息、程序狀態或傳播原因)。
這個 FTP 也沒有定義一組常見錯誤代碼的目標。
設計
這項提案會修改線路格式、來源語言和第一類語言繫結。
Wire 格式
傳輸格式規格目前有關於墓誌銘的章節。這個部分將修訂如下:
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 型別。
我們會在原始繫結的章節中,新增下列 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++ 繫結,以執行下列操作:
fidl::Binding 會在收到 Epitaph 時立即關閉管道。
開發人員可以使用 fidl::Binding::Close 關閉管道
錯誤代碼會透過 set_error_handler() 傳播至用戶端設定的錯誤處理常式。我們將新增 error_handler 變體,該變體會採用代表錯誤代碼的整數變數,並移除現有變體。未來可能會有「合理的預設」錯誤處理常式,但目前尚不清楚會是什麼。
這個管道的任何待處理讀取作業都會傳回 ZX_ERR_PEER_CLOSED。
C++ 繫結的 CL:https://fuchsia-review.googlesource.com/c/garnet/+/177939
其他繫結也需要更新,包括 Dart、Rust 和 Go。
說明文件和範例
文件會按照上一節的說明更新。
開發人員指南
墓誌銘的用途是讓伺服器向用戶端提供有關管道處置和可能正在傳輸的要求的可採取行動資訊。
本節說明墓誌銘的預期行為和用途。
墓誌銘訊息只會從伺服器傳送至用戶端,絕不會反向傳送。如果傳送,則必須是伺服器在關閉管道端點前,傳送給用戶端的最後一則訊息。
用戶端收到墓誌銘訊息時,必須立即關閉管道的結尾。不得嘗試從可能由不符規定的伺服器實作傳送的管道讀取任何其他訊息。
如果用戶端發現對等互連已關閉,但未收到墓誌銘,則必須視為已收到
ZX_ERR_PEER_CLOSED墓誌銘;這兩種狀態在語意上是等效的。當通訊協定達到指定的成功結束狀態,導致管道關閉時,伺服器應傳送
ZX_OK墓誌銘。a. 舉例來說,當用戶端在代表個別資料庫交易的介面上呼叫 Commit() 時,伺服器應嘗試套用所要求的變更。如果成功,伺服器必須在關閉管道的結尾前傳送
ZX_OK墓誌銘。客戶可能會合理地認為ZX_OK墓誌銘表示交易已成功提交。b. 反例:許多通訊協定沒有指定的成功結束狀態;用戶端預期能夠連線至伺服器,並發出無限數量的要求,直到用戶端關閉自己的管道端為止,都不會觀察到對等互連關閉。在這些情況下,伺服器關閉管道的結尾會構成異常結束狀態,因此伺服器絕不應傳送
ZX_OK墓誌銘。如果通訊協定未達到指定的成功結束狀態,伺服器可能會在關閉管道的結尾前傳送非
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,因為 IO 使用 0x80000001。 目前沒有任何項目依賴使用 0x80000001 的 Epitaph。否則不必擔心回溯相容性問題。
效能
不適用
安全性
不支援這項操作。
測試
這項功能的單元測試會新增至適當的 FIDL 繫結。每個支援的 FIDL 繫結獲得支援後,我們應擴增 FIDL 相容性測試集。
缺點、替代方案和未知事項
我們考慮建立包含 Epitaph 事件的 System 介面,做為所有其他介面訊息的父項。單獨的墓誌銘不足以證明需要進行如此大幅度的變更。目前有兩項導入障礙。首先,衍生型別目前無法運作,但這項限制很快就會解除。接著,由於這項提案會變更執行階段,而 FIDL 剖析器 / 產生器取決於執行階段,因此導入系統訊息並嘗試在執行階段中使用,會導致循環依附元件。
這次 FTP 造成的 API 變更,不會妨礙 Epitaph 支援功能在日後移至系統訊息。
有人提議將部分墓誌銘處理作業併入來源語言,允許將 zx_status 標記對應為 FIDL 定義的列舉。這項功能將延後推出。
建議的實作方式有競爭條件。如果一個執行緒寫入訊息,而另一個執行緒同時關閉管道,則墓誌銘可能會在其他執行緒的訊息之前寫入,但會在呼叫 zx_handle_close() 之前。替代方案包括鎖定管道或提供明確的系統呼叫。我們從執行緒不安全版本著手,進一步瞭解問題空間。