Skip to content

Commit 14892a7

Browse files
committed
Fix panic in multiListener
If Close() is called concurrently, both goroutines could pass the select’s default case before either of them executes close(), resulting in the channel being closed twice
1 parent 4c0f3b2 commit 14892a7

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

net/multi_listen.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"net"
2323
"sync"
24+
"sync/atomic"
2425
)
2526

2627
// connErrPair pairs conn and error which is returned by accept on sub-listeners.
@@ -38,6 +39,7 @@ type multiListener struct {
3839
connCh chan connErrPair
3940
// stopCh communicates from parent to child listeners.
4041
stopCh chan struct{}
42+
closed atomic.Bool
4143
}
4244

4345
// compile time check to ensure *multiListener implements net.Listener
@@ -150,10 +152,8 @@ func (ml *multiListener) Accept() (net.Conn, error) {
150152
// the go-routines to exit.
151153
func (ml *multiListener) Close() error {
152154
// Make sure this can be called repeatedly without explosions.
153-
select {
154-
case <-ml.stopCh:
155+
if !ml.closed.CompareAndSwap(false, true) {
155156
return fmt.Errorf("use of closed network connection")
156-
default:
157157
}
158158

159159
// Tell all sub-listeners to stop.

0 commit comments

Comments
 (0)