上下文句柄的失败语义
本主题讨论上下文句柄的失败语义。
关闭上下文句柄失败时的失败语义
假设客户端应用程序尝试关闭服务器上打开的上下文句柄,而无需关闭客户端进程。 此外,假设对服务器的调用关闭上下文句柄失败(例如,客户端内存不足)。 处理这种情况的正确方法是调用 RpcSsDestroyClientContext 函数。 在这种情况下,客户端会清理其上下文句柄的一侧,并中止关闭与服务器的连接。 由于连接实际上是一个连接池(请参阅 RPC 和网络),因此每个打开的绑定或上下文句柄都有一个引用进行引用计数,因此通过调用 RpcSsDestroyClientContext 函数来销毁上下文句柄实际上不会破坏连接。 相反,它会递减连接池的引用计数。 若要关闭池中的连接,客户端需要从客户端进程关闭所有绑定句柄和上下文句柄。 然后,池中的所有连接都会关闭,并启动并清理服务器运行机制。
在更改上下文句柄状态期间失败语义
本节中的信息指 Windows XP 和更高版本平台。
上下文句柄只是函数的参数。 当参数封送或取消封送时,上下文句柄状态中的所有更改都会发生。 例如,如果客户端打开上下文句柄(将它从 NULL 更改为非NULL),则 RPC 运行时实际上不会打开句柄的 RPC 部分,直到将参数封送到客户端为止。 在此期间可能会发生故障。 由于各种可能的网络或资源条件低,数据包传送到客户端可能会失败。 或者服务器例程在尝试更改上下文句柄时可能会引发异常。 在这些或其他故障情况下,客户端和服务器可能会获得上下文句柄的不一致视图。 本部分介绍上下文句柄的状态规则,以及客户端和服务器代码在各种故障条件下的责任。
NULL 上下文句柄到达,但服务器例程遇到故障并引发异常。
服务器例程负责清理它可能已创建的任何上下文句柄相关状态。 RPC 运行时会清理其状态。
非NULL 上下文句柄到达,但服务器例程遇到失败并引发异常。
如果服务器例程关闭了上下文句柄,则客户端将不知道它,因为调用不会成功;进一步使用上下文句柄将导致客户端出现RPC_X_SS_CONTEXT_MISMATCH错误。 如果服务器例程未修改上下文句柄,客户端仍可使用它。 如果服务器例程更改存储在服务器上下文中的信息,则来自客户端的新调用将使用该信息。
非NULL 上下文句柄到达,服务器例程将关闭句柄,但封送处理后,上下文句柄封送失败或封送处理失败。
上下文句柄已关闭,使用此上下文句柄的此客户端进一步调用会导致客户端出现RPC_X_SS_CONTEXT_MISMATCH错误。
NULL 上下文句柄到达,服务器为此句柄创建其上下文,但在上下文句柄封送失败后进行封送处理或封送处理失败。
在这种情况下,RPC 运行时调用此上下文句柄的运行,并清除此上下文句柄的 RPC 状态。 不会在客户端创建上下文句柄。
非NULL 上下文句柄到达,服务器要么不更改上下文句柄,要么更改存储在服务器上下文中的信息,封送处理在封送上下文后会失败。
来自客户端的新调用将使用服务器具有的上下文句柄。
NULL 上下文句柄到达,服务器不会将其设置为除 NULL以外的任何内容,但在封送上下文句柄之前调用失败。
在这种情况下,不会在客户端上创建上下文句柄。
非NULL 上下文句柄到达,服务器将其设置为 NULL,但封送处理在封送上下文句柄之前失败。
在这种情况下,上下文句柄在服务器上保持关闭状态,当客户端尝试使用上下文句柄时,客户端将RPC_X_SS_CONTEXT_MISMATCH错误。
NULL 上下文句柄到达服务器,服务器将其设置为非NULL,但封送处理在封送上下文句柄之前失败。
要调用上下文句柄运行,以便服务器可以清理,并且不会在客户端上创建上下文句柄。
非NULL 上下文句柄到达,服务器要么不更改上下文句柄,要么更改存储在服务器上下文中的信息,在封送上下文句柄之前封送处理失败。
来自客户端的新调用将使用服务器上的状态。
上下文句柄声明为返回值,服务器例程在封送上下文句柄之前返回 NULL,封送处理失败。
在这种情况下,不会在客户端上创建新上下文。
上下文句柄声明为返回值,服务器例程在封送上下文句柄之前返回非NULL,封送处理失败。
RPC 运行时调用上下文句柄运行例程,以使其有机会清理,并且客户端上未创建任何新上下文。