Skip to content

Commit

Permalink
relay: Precalculate frame properties before writing to sendCh
Browse files Browse the repository at this point in the history
Previously, we wrote a frame to sendCh, then checked properties on the
frame. After writing to sendCh, the receiver may write out the frame and
release the frame back to the pool, before we've had a chance to run.

This meant we could be deleting the wrong relay item (or not deleting
anything), which manifested itself as a timeout error frame being sent
after a call response frame.
  • Loading branch information
prashantv committed Jun 22, 2016
1 parent e978a5a commit 2c691a1
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions relay.go
Expand Up @@ -197,14 +197,16 @@ func (r *Relayer) Relay(f *Frame) error {

// Receive receives frames intended for this connection.
func (r *Relayer) Receive(f *Frame, fType frameType) {
id := f.Header.ID

// If we receive a response frame, we expect to find that ID in our outbound.
// If we receive a request frame, we expect to find that ID in our inbound.
items := r.receiverItems(fType)

item, ok := items.Get(f.Header.ID)
item, ok := items.Get(id)
if !ok {
r.logger.WithFields(
LogField{"ID", f.Header.ID},
LogField{"id", id},
).Warn("Received a frame without a RelayItem.")
return
}
Expand All @@ -221,12 +223,17 @@ func (r *Relayer) Receive(f *Frame, fType frameType) {
}
}

// When we write the frame to sendCh, we lose ownership of the frame, and it
// may be released to the frame pool at any point.
finished := finishesCall(f)

// TODO: Add some sort of timeout here to avoid blocking forever on a
// stalled connection.
r.conn.sendCh <- f
if finishesCall(f) {

if finished {
items := r.receiverItems(fType)
r.finishRelayItem(items, f.Header.ID)
r.finishRelayItem(items, id)
}
}

Expand Down

0 comments on commit 2c691a1

Please sign in to comment.