diff options
author | Meng Zhuo <mzh@golangcn.org> | 2020-11-28 18:09:21 +0800 |
---|---|---|
committer | Meng Zhuo <mzh@golangcn.org> | 2020-12-16 02:14:48 +0000 |
commit | 08b5091d03621527d57da7e1ab30584dee167e6d (patch) | |
tree | 5fc097bcbbaf76b6a7a382e2dee9d045eb563fb6 | |
parent | 8981092d71aee273d27b0e11cf932a34d4d365c1 (diff) | |
download | go-08b5091d03621527d57da7e1ab30584dee167e6d.tar.gz go-08b5091d03621527d57da7e1ab30584dee167e6d.zip |
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>
-rw-r--r-- | src/net/conn_test.go | 2 | ||||
-rw-r--r-- | src/net/mockserver_test.go | 12 | ||||
-rw-r--r-- | src/net/protoconn_test.go | 2 | ||||
-rw-r--r-- | src/net/server_test.go | 4 | ||||
-rw-r--r-- | src/net/tcpsock_test.go | 2 |
5 files changed, 14 insertions, 8 deletions
diff --git a/src/net/conn_test.go b/src/net/conn_test.go index 6854898da2..771cabcd3c 100644 --- a/src/net/conn_test.go +++ b/src/net/conn_test.go @@ -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) } diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index 9faf173679..867e31e9ae 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -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 { diff --git a/src/net/protoconn_test.go b/src/net/protoconn_test.go index 9f6772c7d1..6f83f52681 100644 --- a/src/net/protoconn_test.go +++ b/src/net/protoconn_test.go @@ -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) diff --git a/src/net/server_test.go b/src/net/server_test.go index 2673b87718..4ac5443e6a 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -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) } diff --git a/src/net/tcpsock_test.go b/src/net/tcpsock_test.go index 6e905aa091..d6172bc503 100644 --- a/src/net/tcpsock_test.go +++ b/src/net/tcpsock_test.go @@ -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) } |