From cbe87cb2ed940ea37951164b1c8165d9e6369f0f Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sun, 28 Aug 2016 20:04:47 -0700 Subject: [PATCH] Fix fd-leak in rpcClient close it pro-actively. --- cmd/auth-rpc-client.go | 9 ++++++--- cmd/net-rpc-client.go | 31 ++++++++++++------------------- cmd/server-main.go | 4 ++-- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/cmd/auth-rpc-client.go b/cmd/auth-rpc-client.go index 6f8fa037f..1ea8014d4 100644 --- a/cmd/auth-rpc-client.go +++ b/cmd/auth-rpc-client.go @@ -149,11 +149,14 @@ func (authClient *AuthRPCClient) Call(serviceMethod string, args interface { args.SetToken(authClient.token) args.SetTimestamp(authClient.tstamp) - // .. + // Call the underlying rpc. err = authClient.rpc.Call(serviceMethod, args, reply) + // Invalidate token to mark for re-login on subsequent reconnect. - if err != nil && err == rpc.ErrShutdown { - authClient.isLoggedIn = false + if err != nil { + if err.Error() == rpc.ErrShutdown.Error() { + authClient.isLoggedIn = false + } } } return err diff --git a/cmd/net-rpc-client.go b/cmd/net-rpc-client.go index e3b02d016..14ff2d2f1 100644 --- a/cmd/net-rpc-client.go +++ b/cmd/net-rpc-client.go @@ -75,7 +75,6 @@ func (rpcClient *RPCClient) dialRPCClient() (*rpc.Client, error) { // Call makes a RPC call to the remote endpoint using the default codec, namely encoding/gob. func (rpcClient *RPCClient) Call(serviceMethod string, args interface{}, reply interface{}) error { - // Make a copy below so that we can safely (continue to) work with the rpc.Client. // Even in the case the two threads would simultaneously find that the connection is not initialised, // they would both attempt to dial and only one of them would succeed in doing so. @@ -93,15 +92,24 @@ func (rpcClient *RPCClient) Call(serviceMethod string, args interface{}, reply i // If the RPC fails due to a network-related error, then we reset // rpc.Client for a subsequent reconnect. err := rpcLocalStack.Call(serviceMethod, args, reply) - if IsRPCError(err) { - rpcClient.clearRPCClient() + if err != nil { + if err.Error() == rpc.ErrShutdown.Error() { + // Reset rpcClient.rpc to nil to trigger a reconnect in future + // and close the underlying connection. + rpcClient.clearRPCClient() + + // Close the underlying connection. + rpcLocalStack.Close() + + // Set rpc error as rpc.ErrShutdown type. + err = rpc.ErrShutdown + } } return err } // Close closes the underlying socket file descriptor. func (rpcClient *RPCClient) Close() error { - // See comment above for making a copy on local stack rpcLocalStack := rpcClient.getRPCClient() @@ -115,18 +123,3 @@ func (rpcClient *RPCClient) Close() error { rpcClient.clearRPCClient() return rpcLocalStack.Close() } - -// IsRPCError returns true if the error value is due to a network related -// failure, false otherwise. -func IsRPCError(err error) bool { - if err == nil { - return false - } - // The following are net/rpc specific errors that indicate that - // the connection may have been reset. Reset rpcClient.rpc to nil - // to trigger a reconnect in future. - if err == rpc.ErrShutdown { - return true - } - return false -} diff --git a/cmd/server-main.go b/cmd/server-main.go index 976da0ac4..4321f9234 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -48,9 +48,9 @@ var serverCmd = cli.Command{ minio {{.Name}} - {{.Usage}} USAGE: - minio {{.Name}} [OPTIONS] PATH [PATH...] + minio {{.Name}} [FLAGS] PATH [PATH...] -OPTIONS: +FLAGS: {{range .Flags}}{{.}} {{end}} ENVIRONMENT VARIABLES: