From 8b593975b68d757deba52c07bbdbc4d722848f4e Mon Sep 17 00:00:00 2001 From: Kleissner Date: Mon, 1 Nov 2021 09:02:35 +0100 Subject: [PATCH] UDT: Fix closing channel twice in race condition when calling udtSocket.Close() multiple times --- udt/udtsocket.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/udt/udtsocket.go b/udt/udtsocket.go index dd2d398..20a764e 100644 --- a/udt/udtsocket.go +++ b/udt/udtsocket.go @@ -86,6 +86,8 @@ type udtSocket struct { sendPacket chan packet.Packet // packets to send out on the wire (once goManageConnection is running) shutdownEvent chan shutdownMessage // channel signals the connection to be shutdown sockClosed chan struct{} // closed when socket is closed + closeMutex sync.Mutex + isClosed bool // timers connTimeout <-chan time.Time // connecting: fires when connection attempt times out @@ -290,10 +292,15 @@ func (s *udtSocket) Write(p []byte) (n int, err error) { // Read operations will return an error // (required for net.Conn implementation) func (s *udtSocket) Close() error { - if !s.isOpen() { + s.closeMutex.Lock() + defer s.closeMutex.Unlock() + + if s.isClosed || !s.isOpen() { return nil // already closed } + s.isClosed = true + close(s.messageOut) return nil } @@ -462,13 +469,12 @@ func (s *udtSocket) startConnect() error { } func (s *udtSocket) goManageConnection() { - sockClosed := s.sockClosed for { select { case <-s.lingerTimer: // linger timer expired, shut everything down s.shutdown(sockStateClosed, false, nil) return - case _, _ = <-sockClosed: + case <-s.sockClosed: return case p := <-s.sendPacket: ts := uint32(time.Now().Sub(s.created) / time.Microsecond)