net/rpc: do not leak client socket on closed connection

Fixes #6897.

LGTM=bradfitz
R=golang-codereviews, bradfitz, r, rsc
CC=golang-codereviews
https://golang.org/cl/91230045
This commit is contained in:
David Crawshaw 2014-05-11 14:46:44 -07:00 committed by Brad Fitzpatrick
parent 91a576eb0f
commit 82ca308743
2 changed files with 44 additions and 6 deletions

View file

@ -39,14 +39,16 @@ type Call struct {
// with a single Client, and a Client may be used by
// multiple goroutines simultaneously.
type Client struct {
mutex sync.Mutex // protects pending, seq, request
sending sync.Mutex
codec ClientCodec
sending sync.Mutex
mutex sync.Mutex // protects following
request Request
seq uint64
codec ClientCodec
pending map[uint64]*Call
closing bool
shutdown bool
closing bool // user has called Close
shutdown bool // server has told us to stop
}
// A ClientCodec implements writing of RPC requests and
@ -274,7 +276,7 @@ func Dial(network, address string) (*Client, error) {
func (client *Client) Close() error {
client.mutex.Lock()
if client.shutdown || client.closing {
if client.closing {
client.mutex.Unlock()
return ErrShutdown
}

View file

@ -0,0 +1,36 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rpc
import (
"errors"
"testing"
)
type shutdownCodec struct {
responded chan int
closed bool
}
func (c *shutdownCodec) WriteRequest(*Request, interface{}) error { return nil }
func (c *shutdownCodec) ReadResponseBody(interface{}) error { return nil }
func (c *shutdownCodec) ReadResponseHeader(*Response) error {
c.responded <- 1
return errors.New("shutdownCodec ReadResponseHeader")
}
func (c *shutdownCodec) Close() error {
c.closed = true
return nil
}
func TestCloseCodec(t *testing.T) {
codec := &shutdownCodec{responded: make(chan int)}
client := NewClientWithCodec(codec)
<-codec.responded
client.Close()
if !codec.closed {
t.Error("client.Close did not close codec")
}
}