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() defer ls.teardown()
ch := make(chan error, 1) 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 { if err := ls.buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

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

View file

@ -72,7 +72,7 @@ func TestTCPConnSpecificMethods(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ch := make(chan error, 1) 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() ls, err := (&streamListener{Listener: ln}).newLocalServer()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -86,7 +86,7 @@ func TestTCPServer(t *testing.T) {
} }
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
ch := tpchs[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 { if err := lss[i].buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -178,7 +178,7 @@ func TestUnixAndUnixpacketServer(t *testing.T) {
} }
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
ch := tpchs[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 { if err := lss[i].buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -393,7 +393,7 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
} }
defer ls.teardown() defer ls.teardown()
ch := make(chan error, 1) 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 { if err := ls.buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }