From 0e7c2f9e7f6f25694fd838088bef0432e85fef06 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Tue, 4 Jul 2017 20:06:14 -0700 Subject: [PATCH] memberlist: Monkey patch memberlist to fix port 0 behavior. https://github.com/hashicorp/memberlist/pull/128 --- .../hashicorp/memberlist/memberlist.go | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/vendor/github.com/hashicorp/memberlist/memberlist.go b/vendor/github.com/hashicorp/memberlist/memberlist.go index e4b0d7347d..9ea195cfc3 100644 --- a/vendor/github.com/hashicorp/memberlist/memberlist.go +++ b/vendor/github.com/hashicorp/memberlist/memberlist.go @@ -113,14 +113,43 @@ func newMemberlist(conf *Config) (*Memberlist, error) { BindPort: conf.BindPort, Logger: logger, } - nt, err := NewNetTransport(nc) + + // See comment below for details about the retry in here. + makeNetRetry := func(limit int) (*NetTransport, error) { + for try := 0; try < limit; try++ { + nt, err := NewNetTransport(nc) + if err == nil { + return nt, nil + } + + if strings.Contains(err.Error(), "address already in use") { + logger.Printf("[DEBUG] Got bind error: %v", err) + continue + } + } + + return nil, fmt.Errorf("ran out of tries to obtain an address") + } + + // The dynamic bind port operation is inherently racy because + // even though we are using the kernel to find a port for us, we + // are attempting to bind multiple protocols (and potentially + // multiple addresses) with the same port number. We build in a + // few retries here since this often gets transient errors in + // busy unit tests. + limit := 1 + if conf.BindPort == 0 { + limit = 10 + } + + nt, err := makeNetRetry(limit) if err != nil { return nil, fmt.Errorf("Could not set up network transport: %v", err) } - if conf.BindPort == 0 { port := nt.GetAutoBindPort() conf.BindPort = port + conf.AdvertisePort = port logger.Printf("[DEBUG] Using dynamic bind port %d", port) } transport = nt