From 8ce579aac9a89aafc7ff56a71c83c9db6aebb57e Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Thu, 13 Apr 2017 10:48:06 -0700 Subject: [PATCH 1/3] pkg/transport: add 'IsClosedConnError' Signed-off-by: Gyu-Ho Lee --- pkg/transport/listener.go | 10 ++++++++++ pkg/transport/listener_test.go | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/pkg/transport/listener.go b/pkg/transport/listener.go index 88c8923b8..3e45a8446 100644 --- a/pkg/transport/listener.go +++ b/pkg/transport/listener.go @@ -27,6 +27,7 @@ import ( "net" "os" "path/filepath" + "strings" "time" "github.com/coreos/etcd/pkg/tlsutil" @@ -269,3 +270,12 @@ func ShallowCopyTLSConfig(cfg *tls.Config) *tls.Config { } return &ncfg } + +// IsClosedConnError returns true if the error is from closing listener, cmux. +// copied from golang.org/x/net/http2/http2.go +func IsClosedConnError(err error) bool { + // 'use of closed network connection' (Go <=1.8) + // 'use of closed file or network connection' (Go >1.8, internal/poll.ErrClosing) + // 'mux: listener closed' (cmux.ErrListenerClosed) + return err != nil && strings.Contains(err.Error(), "closed") +} diff --git a/pkg/transport/listener_test.go b/pkg/transport/listener_test.go index d5ff31789..b3217333a 100644 --- a/pkg/transport/listener_test.go +++ b/pkg/transport/listener_test.go @@ -274,3 +274,15 @@ func TestNewListenerTLSInfoSelfCert(t *testing.T) { } testNewListenerTLSInfoAccept(t, tlsinfo) } + +func TestIsClosedConnError(t *testing.T) { + l, err := NewListener("testsocket", "unix", nil) + if err != nil { + t.Errorf("error listening on unix socket (%v)", err) + } + l.Close() + _, err = l.Accept() + if !IsClosedConnError(err) { + t.Fatalf("expect true, got false (%v)", err) + } +} From 56b111df0cf32819545323869b474410d62c9a52 Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Thu, 13 Apr 2017 10:48:24 -0700 Subject: [PATCH 2/3] rafthttp: use 'transport.IsClosedConnError' Signed-off-by: Gyu-Ho Lee --- rafthttp/stream.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/rafthttp/stream.go b/rafthttp/stream.go index 0f29428b2..2a6c620f5 100644 --- a/rafthttp/stream.go +++ b/rafthttp/stream.go @@ -19,7 +19,6 @@ import ( "fmt" "io" "io/ioutil" - "net" "net/http" "path" "strings" @@ -28,6 +27,7 @@ import ( "github.com/coreos/etcd/etcdserver/stats" "github.com/coreos/etcd/pkg/httputil" + "github.com/coreos/etcd/pkg/transport" "github.com/coreos/etcd/pkg/types" "github.com/coreos/etcd/raft/raftpb" "github.com/coreos/etcd/version" @@ -317,7 +317,7 @@ func (cr *streamReader) run() { // all data is read out case err == io.EOF: // connection is closed by the remote - case isClosedConnectionError(err): + case transport.IsClosedConnError(err): default: cr.status.deactivate(failureType{source: t.String(), action: "read"}, err.Error()) } @@ -514,11 +514,6 @@ func (cr *streamReader) resume() { cr.paused = false } -func isClosedConnectionError(err error) bool { - operr, ok := err.(*net.OpError) - return ok && operr.Err.Error() == "use of closed network connection" -} - // checkStreamSupport checks whether the stream type is supported in the // given version. func checkStreamSupport(v *semver.Version, t streamType) bool { From 6c2fb5105dd244cc3bac81c066ff70515dff9e3b Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Thu, 13 Apr 2017 10:48:53 -0700 Subject: [PATCH 3/3] clientv3/integration: use 'transport.IsClosedConnError' Signed-off-by: Gyu-Ho Lee --- clientv3/integration/metrics_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clientv3/integration/metrics_test.go b/clientv3/integration/metrics_test.go index 3543a7fab..6311fe0d7 100644 --- a/clientv3/integration/metrics_test.go +++ b/clientv3/integration/metrics_test.go @@ -58,7 +58,7 @@ func TestV3ClientMetrics(t *testing.T) { } err = srv.Serve(ln) - if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + if err != nil && !transport.IsClosedConnError(err) { t.Fatalf("Err serving http requests: %v", err) } }()