RFC-0053:表情符号

RFC-0053:墓碑
状态已接受
领域
  • FIDL
说明

该方案的目标是允许服务器在关闭连接之前发送一条消息,以说明连接关闭的原因。

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

“您的服务器在这里”

总结

该方案的目标是允许服务器在关闭连接之前发送一条消息,以表明连接关闭的原因。虽然本规范中涵盖了荣誉,但它们尚未实现。

设计初衷

目前,服务器还没有向客户端传达连接关闭原因的标准方法。这样做的效果是,确保错误处理的责任由开发者负责。开发者可以预见到这种情况,并在其消息中内置特殊的错误处理机制,或者直接忽略错误处理(这可能会产生无法诊断的错误)。

一种使用场景是服务器,其中错误大多数是严重的,出现错误时,与客户端的所有连接都会关闭。在这种情况下,开发者需要一种通用的错误报告机制,因为对方法的所有进行中的调用都将以相同的错误终止。除此以外,为每个方法声明潜在错误的做法既麻烦又麻烦。

此 FTP 的目标不是提供全面的错误报告机制。具体而言,向连接的另一端传达大量详细信息(包括详细消息、进程状态或传播的原因)的功能不在考虑范围之内。

此外,该 FTP 的目标也不是定义一组常见错误代码。

设计

此方案会修改传输格式、源语言和第一类语言绑定。

电汇格式

传输格式规范中目前有一个关于《圣书记》的章节。本节将修订为以下内容:

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++、以 Rust 编写的 Result<t、e=""> 传递错误代码,在 Dart 中传递异常),则采用不同方式处理错误。</t,>

我们将向 C 绑定添加方法 fidl_epitaph_write(channel, 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 会在收到圣书后立即关闭频道。

开发者将可以使用 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。

文档和示例

本文档将按照上一部分中的说明进行更新。

开发者指南

此标志的目的是让服务器能够向客户端提供有关处理信道和可能正在传输的请求的可操作信息。

本部分将介绍歌词的预期行为和用法。

  1. 台词消息仅从服务器发送到客户端,绝不会发送到其他方向。如果发送,它必须是服务器向客户端发送的最后一条消息,在服务器关闭其通道末尾之前。

  2. 当客户端收到 epitaph 消息时,必须立即关闭其通道的末尾。不得尝试从信道中读取可能由不合规的服务器实现发送的任何其他消息。

  3. 如果客户端观察到对等方已关闭,却未收到相应 epitaph,则必须像收到 ZX_ERR_PEER_CLOSED epitaph 一样继续操作;这两种状态在语义上是等效的。

  4. 如果通道关闭是预期协议会由于协议达到其指定的成功结束状态而产生副作用,则服务器应发送 ZX_OK epitaph。

    a. 示例:当客户端在表示单个数据库事务的接口上调用 Commit() 时,服务器应尝试应用请求的更改。如果成功,服务器必须在关闭通道末尾之前发送 ZX_OK epitaph。客户端可以合理地认为,ZX_OK 标记表示事务已成功提交。

    b. 计数器示例:许多协议都没有指定成功的结束状态;客户端希望能够连接到服务器并发出无限数量的请求,而不会观察到对等方在客户端关闭其自己的通道端之前关闭。在这些情况下,服务器关闭通道末尾会导致异常结束状态,因此服务器绝不应发送 ZX_OK 缩容词。

  5. 服务器可以出于任何原因在关闭频道结束之前发送非 ZX_OK epitaph(协议到达其指定的成功结束状态除外)。我们建议您采用以下惯例:

    a. 如果服务器因为客户端向其发送了格式错误的 FIDL 消息而关闭连接,应发送 ZX_ERR_INVALID_ARGS epitaph。

    b. 如果服务器因为客户端向其发送的请求在其当前状态下无效而关闭连接,应发送 ZX_ERR_BAD_STATE epitaph。

    c. 如果当客户端尝试通过服务发现机制连接到服务器时无法访问(例如无法启动),此机制应发送 ZX_ERR_UNAVAILABLE EPitaph。(另请参阅此例程。)

    d. 如果服务器因并非响应客户端执行的操作(例如关闭或内存不足)而无法继续传送协议,则无需发送任何影像内容。如上所述,客户端会将此视为 ZX_ERR_PEER_CLOSED

    e. 如果服务器遇到应用特定错误,则应发送应用定义的错误代码。例如,如果服务器控制文件系统,而用户尝试执行其无权执行的写入,则可能希望关闭连接并报错。

    f. 该列表并未列出所有相关网址。服务器可能会视情况发送其他错误。一如既往,我们建议 FIDL 作者明确记录其协议可能会返回的错误,包括表名。

向后兼容性

FIDL 文档目前声明 0x80000001 是书名的序数。我们将其更改为 0xFFFFFFFF,因为 IO 正在使用 0x80000001。 目前没有任何内容依赖于使用 0x80000001 的墓碑。否则,不存在向后兼容性问题。

性能

不适用

安全性

不适用。

测试

此功能的单元测试将添加到相应的 FIDL 绑定中。在每个受支持的 FIDL 绑定都获得支持后,我们应扩充一组 FIDL 兼容性测试

缺点、替代方案和未知情况

我们考虑过创建一个包含 Epitaph 事件的 System 接口,该事件将是所有其他接口消息的父级。圣书本身并不能保证可以进行如此大的修改。目前在实现方面也存在两个障碍。首先,派生类型目前不起作用,但很快就会发生变化。接下来,由于此方案会更改运行时,并且 FIDL 解析器 / 生成器依赖于运行时,因此引入系统消息并尝试在运行时使用它会导致循环依赖关系。

此 FTP 产生的 API 更改不会阻止 Epitaph 支持移至未来的系统消息。

他们提出了一个想法,即在源语言中纳入一些台词处理,允许将 zx_status 标志映射为 FIDL 定义的枚举。这推迟到未来的工作。

提议的实现方式比较少性。如果一个线程与另一个关闭通道的线程同时写入消息,则 epitaph 可以在另一个线程的消息之前、调用 zx_handle_close() 之前写入。替代方案包括锁定频道或提供显式系统调用。我们将从线程不安全版本开始,以进一步了解问题空间。