1
0
mirror of https://github.com/golang/go synced 2024-11-11 21:30:23 -07:00

net: close connection in localServer teardown

The transponder sets up a deferred close on accepted connections which
is fine after the client reads all data. However there are no mutexes
nor channels to block the transponder from closing. If the scheduler
runs close before the client read, it will cause an EOF failure.

Fixes #42720

Change-Id: Ic21b476c5efc9265a80a2c6f8484efdb5af66405
Reviewed-on: https://go-review.googlesource.com/c/go/+/273672
Run-TryBot: Meng Zhuo <mzh@golangcn.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Meng Zhuo <mzh@golangcn.org>
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Meng Zhuo 2020-11-28 18:09:21 +08:00
parent 8981092d71
commit 08b5091d03
5 changed files with 14 additions and 8 deletions

View File

@ -32,7 +32,7 @@ func TestConnAndListener(t *testing.T) {
}
defer ls.teardown()
ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := ls.buildup(handler); err != nil {
t.Fatal(err)
}

View File

@ -87,6 +87,7 @@ type localServer struct {
lnmu sync.RWMutex
Listener
done chan bool // signal that indicates server stopped
cl []Conn // accepted connection list
}
func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
@ -99,10 +100,16 @@ func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
func (ls *localServer) teardown() error {
ls.lnmu.Lock()
defer ls.lnmu.Unlock()
if ls.Listener != nil {
network := ls.Listener.Addr().Network()
address := ls.Listener.Addr().String()
ls.Listener.Close()
for _, c := range ls.cl {
if err := c.Close(); err != nil {
return err
}
}
<-ls.done
ls.Listener = nil
switch network {
@ -110,7 +117,6 @@ func (ls *localServer) teardown() error {
os.Remove(address)
}
}
ls.lnmu.Unlock()
return nil
}
@ -203,7 +209,7 @@ func newDualStackServer() (*dualStackServer, error) {
}, nil
}
func transponder(ln Listener, ch chan<- error) {
func (ls *localServer) transponder(ln Listener, ch chan<- error) {
defer close(ch)
switch ln := ln.(type) {
@ -220,7 +226,7 @@ func transponder(ln Listener, ch chan<- error) {
ch <- err
return
}
defer c.Close()
ls.cl = append(ls.cl, c)
network := ln.Addr().Network()
if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {

View File

@ -72,7 +72,7 @@ func TestTCPConnSpecificMethods(t *testing.T) {
t.Fatal(err)
}
ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ls.Listener, ch) }
handler := func(ls *localServer, ln Listener) { ls.transponder(ls.Listener, ch) }
ls, err := (&streamListener{Listener: ln}).newLocalServer()
if err != nil {
t.Fatal(err)

View File

@ -86,7 +86,7 @@ func TestTCPServer(t *testing.T) {
}
for i := 0; i < N; i++ {
ch := tpchs[i]
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := lss[i].buildup(handler); err != nil {
t.Fatal(err)
}
@ -178,7 +178,7 @@ func TestUnixAndUnixpacketServer(t *testing.T) {
}
for i := 0; i < N; i++ {
ch := tpchs[i]
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := lss[i].buildup(handler); err != nil {
t.Fatal(err)
}

View File

@ -393,7 +393,7 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
}
defer ls.teardown()
ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := ls.buildup(handler); err != nil {
t.Fatal(err)
}