]> Cypherpunks repositories - gostls13.git/commitdiff
net: close connection in localServer teardown
authorMeng Zhuo <mzh@golangcn.org>
Sat, 28 Nov 2020 10:09:21 +0000 (18:09 +0800)
committerMeng Zhuo <mzh@golangcn.org>
Wed, 16 Dec 2020 02:14:48 +0000 (02:14 +0000)
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>
src/net/conn_test.go
src/net/mockserver_test.go
src/net/protoconn_test.go
src/net/server_test.go
src/net/tcpsock_test.go

index 6854898da2ab09534fa8ecc5176de17dc9314913..771cabcd3cd331d34e1958fdb05cb8b33952d596 100644 (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)
                }
index 9faf173679a5aae939626258f5db821aaa5e3630..867e31e9ae6a55823a237f89fc5335594d085ca4 100644 (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 {
index 9f6772c7d15e08ab0d10f61d5bb9aaeea878442b..6f83f526812f80f080d009cc55547d0d27a5150b 100644 (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)
index 2673b87718c40f4ffc127eb8cbcf9da33c25021f..4ac5443e6a130c5cb251bc799c382cbc825eaa7b 100644 (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)
                        }
index 6e905aa0914b397f2c7c00a6f0a747579a28d204..d6172bc5030996f9ba7b5e75cfc33bc155705518 100644 (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)
                }