Skip to content

Commit 90fde31

Browse files
authored
Merge pull request #715 from hlibman-connamara/resend_request_active
Block Sends when Resend Request is active
2 parents 41798d6 + e954566 commit 90fde31

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

in_session.go

+5
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ func (state inSession) resendMessages(session *session, beginSeqNo, endSeqNo int
230230
return state.generateSequenceReset(session, beginSeqNo, endSeqNo+1, inReplyTo)
231231
}
232232

233+
// resendMutex must always be locked before sendMutex to prevent a potential deadlock
234+
// sendMutex is locked below in session.EnqueueBytesAndSend()
235+
session.resendMutex.Lock()
236+
defer session.resendMutex.Unlock()
237+
233238
seqNum := beginSeqNo
234239
nextSeqNum := seqNum
235240
msg := NewMessage()

in_session_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"testing"
2020
"time"
2121

22+
"github.com/stretchr/testify/mock"
2223
"github.com/stretchr/testify/suite"
2324

2425
"github.com/quickfixgo/quickfix/internal"
@@ -373,6 +374,25 @@ func (s *InSessionTestSuite) TestFIXMsgInResendRequestDoNotSendApp() {
373374
s.State(inSession{})
374375
}
375376

377+
func (s *InSessionTestSuite) TestFIXMsgInResendRequestBlocksSend() {
378+
s.MockApp.On("ToApp").Return(nil)
379+
s.Require().Nil(s.session.send(s.NewOrderSingle()))
380+
s.LastToAppMessageSent()
381+
s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1)
382+
s.NextSenderMsgSeqNum(2)
383+
384+
s.MockStore.On("IterateMessages", mock.Anything, mock.Anything, mock.AnythingOfType("func([]byte) error")).
385+
Run(func(_ mock.Arguments) {
386+
s.Require().Nil(s.session.send(s.NewOrderSingle()))
387+
}).
388+
Return(nil)
389+
390+
s.MockApp.On("FromAdmin").Return(nil)
391+
s.fixMsgIn(s.session, s.ResendRequest(1))
392+
393+
s.NextSenderMsgSeqNum(2)
394+
}
395+
376396
func (s *InSessionTestSuite) TestFIXMsgInTargetTooLow() {
377397
s.IncrNextTargetMsgSeqNum()
378398

session.go

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ type session struct {
4141

4242
// Mutex for access to toSend.
4343
sendMutex sync.Mutex
44+
// Mutex to prevent messages being sent when resendRequest is active
45+
// Must be locked before sendMutex to prevent a potential deadlock
46+
resendMutex sync.RWMutex
4447

4548
sessionEvent chan internal.Event
4649
messageEvent chan bool
@@ -302,6 +305,10 @@ func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error {
302305
return s.queueForSend(msg)
303306
}
304307

308+
// resendMutex must always be locked before sendMutex to prevent a potential deadlock
309+
s.resendMutex.RLock()
310+
defer s.resendMutex.RUnlock()
311+
305312
s.sendMutex.Lock()
306313
defer s.sendMutex.Unlock()
307314

0 commit comments

Comments
 (0)