Skip to content

Commit fae4852

Browse files
committed
Unblock handshake ch on close
1 parent 18c4015 commit fae4852

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

association.go

+20-6
Original file line numberDiff line numberDiff line change
@@ -1375,8 +1375,9 @@ func (a *Association) handleCookieEcho(c *chunkCookieEcho) []*packet {
13751375
a.storedCookieEcho = nil
13761376

13771377
a.setState(established)
1378-
// Note: This is a future place where the user could be notified (COMMUNICATION UP)
1379-
a.handshakeCompletedCh <- nil
1378+
if !a.completeHandshake(nil) {
1379+
return nil
1380+
}
13801381
}
13811382

13821383
p := &packet{
@@ -1404,8 +1405,7 @@ func (a *Association) handleCookieAck() {
14041405
a.storedCookieEcho = nil
14051406

14061407
a.setState(established)
1407-
// Note: This is a future place where the user could be notified (COMMUNICATION UP)
1408-
a.handshakeCompletedCh <- nil
1408+
a.completeHandshake(nil)
14091409
}
14101410

14111411
// The caller should hold the lock.
@@ -2698,13 +2698,13 @@ func (a *Association) onRetransmissionFailure(id int) {
26982698

26992699
if id == timerT1Init {
27002700
a.log.Errorf("[%s] retransmission failure: T1-init", a.name)
2701-
a.handshakeCompletedCh <- ErrHandshakeInitAck
2701+
a.completeHandshake(ErrHandshakeInitAck)
27022702
return
27032703
}
27042704

27052705
if id == timerT1Cookie {
27062706
a.log.Errorf("[%s] retransmission failure: T1-cookie", a.name)
2707-
a.handshakeCompletedCh <- ErrHandshakeCookieEcho
2707+
a.completeHandshake(ErrHandshakeCookieEcho)
27082708
return
27092709
}
27102710

@@ -2752,3 +2752,17 @@ func (a *Association) MaxMessageSize() uint32 {
27522752
func (a *Association) SetMaxMessageSize(maxMsgSize uint32) {
27532753
atomic.StoreUint32(&a.maxMessageSize, maxMsgSize)
27542754
}
2755+
2756+
// completeHandshake sends the given error to handshakeCompletedCh unless the read/write
2757+
// side of the association closes before that can happen. It returns whether it was able
2758+
// to send on the channel or not.
2759+
func (a *Association) completeHandshake(handshakeErr error) bool {
2760+
select {
2761+
// Note: This is a future place where the user could be notified (COMMUNICATION UP)
2762+
case a.handshakeCompletedCh <- handshakeErr:
2763+
return true
2764+
case <-a.closeWriteLoopCh: // check the read/write sides for closure
2765+
case <-a.readLoopCloseCh:
2766+
}
2767+
return false
2768+
}

association_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -3222,6 +3222,10 @@ func TestAssociation_Abort(t *testing.T) {
32223222

32233223
// TestAssociation_createClientWithContext tests that the client is closed when the context is canceled.
32243224
func TestAssociation_createClientWithContext(t *testing.T) {
3225+
// Limit runtime in case of deadlocks
3226+
lim := test.TimeOut(time.Second * 5)
3227+
defer lim.Stop()
3228+
32253229
checkGoroutineLeaks(t)
32263230

32273231
udp1, udp2 := createUDPConnPair()

0 commit comments

Comments
 (0)