Skip to content

Commit

Permalink
PROTON-2843: [Go] Fix segfault on settling a message on closed receivers
Browse files Browse the repository at this point in the history
Deliveries can not be settled after the receiver has been freed. Therefore, this adds a check to ensure that the receiver was not closed (which ensures that `Free` has not been called on the link yet)
  • Loading branch information
PatrickTaibel committed Sep 24, 2024
1 parent dc1c39f commit e50ce7b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
15 changes: 15 additions & 0 deletions go/pkg/electron/electron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,18 @@ func TestHeartbeat(t *testing.T) {
t.Error("expected server side time-out or connection abort error")
}
}

func TestReceiverCloseBeforeAcknowledge(t *testing.T) {
p := newPipe(t, nil, nil)
defer func() { p.close() }()
r, s := p.receiver(Source("foo"))
go func() {
out := s.SendSync(amqp.NewMessageWith(0))
_ = test.ErrorIf(t, test.Differ(Closed, out.Error))
}()
rm, err := r.Receive()
test.FatalIf(t, err)
r.Close(nil)
<-r.Done()
_ = test.ErrorIf(t, test.Differ(Closed, rm.Accept()))
}
16 changes: 12 additions & 4 deletions go/pkg/electron/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
)

// Receiver is a Link that receives messages.
//
type Receiver interface {
Endpoint
LinkSettings
Expand Down Expand Up @@ -201,10 +200,19 @@ type ReceivedMessage struct {

// Acknowledge a ReceivedMessage with the given delivery status.
func (rm *ReceivedMessage) acknowledge(status uint64) error {
return rm.receiver.(*receiver).engine().Inject(func() {
// Deliveries are valid as long as the connection is, unless settled.
rm.pDelivery.SettleAs(uint64(status))
receiverError := make(chan error)
err := rm.receiver.(*receiver).engine().Inject(func() {
// Deliveries are valid as long as the receiver is, unless settled.
err := rm.receiver.Error()
receiverError <- err
if err == nil {
rm.pDelivery.SettleAs(status)
}
})
if err != nil {
return err
}
return <-receiverError
}

// Accept tells the sender that we take responsibility for processing the message.
Expand Down

0 comments on commit e50ce7b

Please sign in to comment.