]> Cypherpunks repositories - gostls13.git/commitdiff
rpc: Add Close() method to rpc.Client to allow graceful connection teardown.
authorRob Pike <r@golang.org>
Fri, 16 Apr 2010 23:17:47 +0000 (16:17 -0700)
committerRob Pike <r@golang.org>
Fri, 16 Apr 2010 23:17:47 +0000 (16:17 -0700)
Fixes #675.

R=rsc, msolo
CC=golang-dev
https://golang.org/cl/882049

src/pkg/rpc/client.go

index cee82ad3c88d738854442c37bcb03ea6fa3888da..6b2ddd6f0ab5c8c92628fa53deaca767e0d983f5 100644 (file)
@@ -37,6 +37,7 @@ type Client struct {
        enc      *gob.Encoder
        dec      *gob.Decoder
        pending  map[uint64]*Call
+       closing  bool
 }
 
 func (client *Client) send(c *Call) {
@@ -72,7 +73,7 @@ func (client *Client) input() {
                response := new(Response)
                err = client.dec.Decode(response)
                if err != nil {
-                       if err == os.EOF {
+                       if err == os.EOF && !client.closing {
                                err = io.ErrUnexpectedEOF
                        }
                        break
@@ -101,7 +102,9 @@ func (client *Client) input() {
                _ = call.Done <- call // do not block
        }
        client.mutex.Unlock()
-       log.Stderr("rpc: client protocol error:", err)
+       if err != os.EOF || !client.closing {
+               log.Stderr("rpc: client protocol error:", err)
+       }
 }
 
 // NewClient returns a new Client to handle requests to the
@@ -146,6 +149,16 @@ func Dial(network, address string) (*Client, os.Error) {
        return NewClient(conn), nil
 }
 
+func (client *Client) Close() os.Error {
+       if client.shutdown != nil || client.closing {
+               return os.ErrorString("rpc: already closed")
+       }
+       client.mutex.Lock()
+       client.closing = true
+       client.mutex.Unlock()
+       return client.conn.Close()
+}
+
 // Go invokes the function asynchronously.  It returns the Call structure representing
 // the invocation.  The done channel will signal when the call is complete by returning
 // the same Call object.  If done is nil, Go will allocate a new channel.