diff --git a/datagram/read.go b/datagram/read.go index 51b1c5d2..c80a0d2c 100644 --- a/datagram/read.go +++ b/datagram/read.go @@ -73,8 +73,13 @@ func (r *DatagramReader) receiveLoop() { logger := log.WithField("session_id", r.session.ID()) logger.Debug("Starting receive loop") - // Ensure we signal completion when this loop exits - r.doneChan = make(chan struct{}) + // Signal completion when this loop exits - doneChan must be initialized + // before this goroutine starts to avoid race conditions with Close() + defer func() { + if r.doneChan != nil { + close(r.doneChan) + } + }() for { // Check for closure in a non-blocking way first diff --git a/datagram/session.go b/datagram/session.go index e72a282c..40e3778d 100644 --- a/datagram/session.go +++ b/datagram/session.go @@ -2,6 +2,7 @@ package datagram import ( "net" + "sync" "github.com/go-i2p/go-sam-go/common" "github.com/go-i2p/i2pkeys" @@ -48,6 +49,9 @@ func (s *DatagramSession) NewReader() *DatagramReader { recvChan: make(chan *Datagram, 10), // Buffer for incoming datagrams errorChan: make(chan error, 1), closeChan: make(chan struct{}), + doneChan: make(chan struct{}), + closed: false, + mu: sync.RWMutex{}, } }