From 739e7907139e0b1124060a6383b77e35c51c515c Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Fri, 2 Feb 2024 19:24:54 +0300 Subject: [PATCH] fixed the issue with closing channel twice --- internal/udp/listener.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/internal/udp/listener.go b/internal/udp/listener.go index be56777..9d79e1b 100644 --- a/internal/udp/listener.go +++ b/internal/udp/listener.go @@ -25,6 +25,9 @@ type Listener struct { chanAccept chan *udpConn chanClosed chan struct{} + + closed bool + closedMu sync.Mutex } // Listen creates a new *Listener and is supposed to be a function similar @@ -56,6 +59,10 @@ var _ net.Listener = (*Listener)(nil) // Accept implements the net.Listener interface for *Listener. func (l *Listener) Accept() (conn net.Conn, err error) { + if l.isClosed() { + return nil, net.ErrClosed + } + select { case conn = <-l.chanAccept: return conn, nil @@ -66,6 +73,14 @@ func (l *Listener) Accept() (conn net.Conn, err error) { // Close implements the net.Listener interface for *Listener. func (l *Listener) Close() (err error) { + if l.isClosed() { + return nil + } + + l.closedMu.Lock() + l.closed = true + l.closedMu.Unlock() + close(l.chanClosed) l.natTableMu.Lock() @@ -82,13 +97,21 @@ func (l *Listener) Addr() (addr net.Addr) { return l.conn.LocalAddr() } +// isClosed returns true if the listener is already closed. +func (l *Listener) isClosed() (ok bool) { + l.closedMu.Lock() + defer l.closedMu.Unlock() + + return l.closed +} + // readLoop implements the listener logic, it reads incoming data and passes it // to the corresponding udpConn. When a new udpConn is created, it is written // to the chanAccept channel. func (l *Listener) readLoop() { buf := make([]byte, 65536) - for { + for !l.isClosed() { n, addr, err := l.conn.ReadFromUDP(buf) if err != nil || n == 0 { @@ -215,6 +238,10 @@ func (c *udpConn) Close() (err error) { c.closedMu.Lock() defer c.closedMu.Unlock() + if c.closed { + return nil + } + c.closed = true close(c.chanClosed)