1
0
mirror of https://github.com/golang/go synced 2024-11-12 08:10:21 -07:00

net/rpc: avoid racy use of closing flag.

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
This commit is contained in:
Roger Peppe 2013-02-25 16:22:00 +00:00
parent cd81db8299
commit 7edd13355f
2 changed files with 25 additions and 4 deletions

View 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()

View 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)