上下文句柄的失败语义

本主题讨论上下文句柄的失败语义。

关闭上下文句柄失败时的失败语义

假设客户端应用程序尝试关闭在服务器上打开的上下文句柄,而不关闭客户端进程。 此外,假设调用服务器以关闭上下文句柄 (失败,例如,客户端内存不足) 。 处理这种情况的正确方法是调用 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 运行时调用上下文句柄运行例程,使其有机会进行清理,并且不会在客户端上创建新上下文。