Skip to content

Commit e46bf47

Browse files
committed
Correctly send receiverLoopbacks that target promisedAnswers.
Worryingly, this was manifesting in the test as a deadlock: we hit the error complaining about it not being an import, but then connection shutdown hung, waiting on tasks. I haven't pinned down exactly what was going on there, but this sidesteps the issue by fixing the thing that was causing a connection abort in the first place.
1 parent 9a40e87 commit e46bf47

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

rpc/rpc.go

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,33 +1639,50 @@ func (c *Conn) handleDisembargo(ctx context.Context, in transport.IncomingMessag
16391639
return exc.WrapError("incoming disembargo", err)
16401640
}
16411641

1642-
imp, ok := client.State().Brand.Value.(*importClient)
1643-
if !ok || imp.c != c {
1644-
client.Release()
1645-
return rpcerr.Failed(errors.New(
1646-
"incoming disembargo: sender loopback requested on a capability that is not an import",
1647-
))
1648-
}
1649-
// TODO(maybe): check generation?
1650-
16511642
// Since this Cap'n Proto RPC implementation does not send imports
16521643
// unless they are fully dequeued, we can just immediately loop back.
16531644
id := d.Context().SenderLoopback()
1645+
16541646
c.withLocked(func(c *lockedConn) {
16551647
c.sendMessage(ctx, func(m rpccp.Message) error {
16561648
d, err := m.NewDisembargo()
16571649
if err != nil {
16581650
return err
16591651
}
1660-
1652+
d.Context().SetReceiverLoopback(id)
16611653
tgt, err := d.NewTarget()
16621654
if err != nil {
16631655
return err
16641656
}
16651657

1666-
tgt.SetImportedCap(uint32(imp.id))
1667-
d.Context().SetReceiverLoopback(id)
1668-
return nil
1658+
brand := client.State().Brand
1659+
if pc, ok := brand.Value.(capnp.PipelineClient); ok {
1660+
if q, ok := c.getAnswerQuestion(pc.Answer()); ok {
1661+
if q.c == (*Conn)(c) {
1662+
pa, err := tgt.NewPromisedAnswer()
1663+
if err != nil {
1664+
return err
1665+
}
1666+
pa.SetQuestionId(uint32(q.id))
1667+
pcTrans := pc.Transform()
1668+
trans, err := pa.NewTransform(int32(len(pcTrans)))
1669+
if err != nil {
1670+
return err
1671+
}
1672+
for i, op := range pcTrans {
1673+
trans.At(i).SetGetPointerField(op.Field)
1674+
}
1675+
}
1676+
return nil
1677+
}
1678+
}
1679+
1680+
imp, ok := brand.Value.(*importClient)
1681+
if ok && imp.c == (*Conn)(c) {
1682+
tgt.SetImportedCap(uint32(imp.id))
1683+
return nil
1684+
}
1685+
return errors.New("target for receiver loopback does not point to the right connection")
16691686

16701687
}, func(err error) {
16711688
defer in.Release()

0 commit comments

Comments
 (0)