diff --git a/capability.go b/capability.go index 4bf85529..fd9e1482 100644 --- a/capability.go +++ b/capability.go @@ -843,6 +843,9 @@ type errorClient struct { // ErrorClient returns a Client that always returns error e. // An ErrorClient does not need to be released: it is a sentinel like a // nil Client. +// +// The returned client's State() method returns a State with its +// Brand.Value set to e. func ErrorClient(e error) *Client { if e == nil { panic("ErrorClient(nil)") @@ -870,7 +873,7 @@ func (ec errorClient) Recv(_ context.Context, r Recv) PipelineCaller { } func (ec errorClient) Brand() Brand { - return Brand{} + return Brand{Value: ec.e} } func (ec errorClient) Shutdown() { diff --git a/rpc/rpc.go b/rpc/rpc.go index c046f20b..0c55f506 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -1181,12 +1181,23 @@ func (c *Conn) isLocalClient(client *capnp.Client) bool { if client == nil { return false } - if ic, ok := client.State().Brand.Value.(*importClient); ok { + + bv := client.State().Brand.Value + + if ic, ok := bv.(*importClient); ok { // If the connections are different, we must be proxying // it, so as far as this connection is concerned, it lives // on our side. return ic.c != c } + + if _, ok := bv.(error); ok { + // Returned by capnp.ErrorClient. No need to treat this as + // local; all methods will just return the error anyway, + // so violating E-order will have no effect on the results. + return false + } + // TODO: We should return false for results from pending remote calls // as well. But that can wait until sendCap() actually emits // CapDescriptors of type receiverAnswer, since until then it won't