mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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:
parent
8981092d71
commit
08b5091d03
5 changed files with 14 additions and 8 deletions
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue