Skip to content

Commit

Permalink
net/rpc: do not leak client socket on closed connection
Browse files Browse the repository at this point in the history
Fixes #6897.

LGTM=bradfitz
R=golang-codereviews, bradfitz, r, rsc
CC=golang-codereviews
https://golang.org/cl/91230045
  • Loading branch information
crawshaw authored and bradfitz committed May 11, 2014
1 parent 91a576e commit 82ca308
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
14 changes: 8 additions & 6 deletions src/pkg/net/rpc/client.go
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down
36 changes: 36 additions & 0 deletions src/pkg/net/rpc/client_test.go
@@ -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")
}
}

0 comments on commit 82ca308

Please sign in to comment.