]> Cypherpunks repositories - gostls13.git/commitdiff
net/rpc: avoid racy use of closing flag.
authorRoger Peppe <rogpeppe@gmail.com>
Mon, 25 Feb 2013 16:22:00 +0000 (16:22 +0000)
committerRoger Peppe <rogpeppe@gmail.com>
Mon, 25 Feb 2013 16:22:00 +0000 (16:22 +0000)
It's accessed without mutex protection
in a different goroutine from the one that
sets it.

Also make sure that Client.Call after Client.Close
will reliably return ErrShutdown, and that clients
see ErrShutdown rather than io.EOF when appropriate.

Suggestions welcome for a way to reliably test
the mutex issue.

R=r, iant
CC=golang-dev
https://golang.org/cl/7338045

src/pkg/net/rpc/client.go
src/pkg/net/rpc/server_test.go

index ee3cc4d34d53a66f25fde463e4f482fe277ec485..4b0c9c3bba20efcfd4f8bc22d790e71cafa5c90b 100644 (file)
@@ -71,7 +71,7 @@ func (client *Client) send(call *Call) {
 
        // Register this call.
        client.mutex.Lock()
-       if client.shutdown {
+       if client.shutdown || client.closing {
                call.Error = ErrShutdown
                client.mutex.Unlock()
                call.done()
@@ -105,9 +105,6 @@ func (client *Client) input() {
                response = Response{}
                err = client.codec.ReadResponseHeader(&response)
                if err != nil {
-                       if err == io.EOF && !client.closing {
-                               err = io.ErrUnexpectedEOF
-                       }
                        break
                }
                seq := response.Seq
@@ -150,6 +147,13 @@ func (client *Client) input() {
        client.mutex.Lock()
        client.shutdown = true
        closing := client.closing
+       if err == io.EOF {
+               if closing {
+                       err = ErrShutdown
+               } else {
+                       err = io.ErrUnexpectedEOF
+               }
+       }
        for _, call := range client.pending {
                call.Error = err
                call.done()
index db7778dcb25faf7ae7d4a0affccd07d66df62d00..8a153062356e44882c506e56509a47692a82c030 100644 (file)
@@ -524,6 +524,23 @@ func TestTCPClose(t *testing.T) {
        }
 }
 
+func TestErrorAfterClientClose(t *testing.T) {
+       once.Do(startServer)
+
+       client, err := dialHTTP()
+       if err != nil {
+               t.Fatalf("dialing: %v", err)
+       }
+       err = client.Close()
+       if err != nil {
+               t.Fatal("close error:", err)
+       }
+       err = client.Call("Arith.Add", &Args{7, 9}, new(Reply))
+       if err != ErrShutdown {
+               t.Errorf("Forever: expected ErrShutdown got %v", err)
+       }
+}
+
 func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
        b.StopTimer()
        once.Do(startServer)