diff --git a/gossip/gossip.go b/gossip/gossip.go index 2b983376f..a5b4e9299 100644 --- a/gossip/gossip.go +++ b/gossip/gossip.go @@ -93,6 +93,17 @@ func (g *memberSet) Open() (err error) { return nil } +// Close attempts to gracefully leave the cluster, and finally calls shutdown +// after (at most) a timeout period. +func (g *memberSet) Close() error { + leaveErr := g.memberlist.Leave(5 * time.Second) + shutdownErr := g.memberlist.Shutdown() + if leaveErr != nil || shutdownErr != nil { + return fmt.Errorf("leaving: '%v', shutting down: '%v'", leaveErr, shutdownErr) + } + return nil +} + // joinWithRetry wraps the standard memberlist Join function in a retry. func (g *memberSet) joinWithRetry(hosts []string) error { err := retry(60, 2*time.Second, func() error { diff --git a/server/server.go b/server/server.go index e83cc1c1c..d5d711e56 100644 --- a/server/server.go +++ b/server/server.go @@ -62,6 +62,7 @@ type Command struct { // Gossip transport gossipTransport *gossip.Transport + gossipMemberSet io.Closer // Standard input/output *pilosa.CmdIO @@ -326,6 +327,8 @@ func (m *Command) setupNetworking() error { if err != nil { return errors.Wrap(err, "getting memberset") } + m.gossipMemberSet = gossipMemberSet + return errors.Wrap(gossipMemberSet.Open(), "opening gossip memberset") } @@ -341,12 +344,16 @@ func (m *Command) Close() error { var logErr error handlerErr := m.Handler.Close() serveErr := m.Server.Close() + var gossipErr error + if m.gossipMemberSet != nil { + gossipErr = m.gossipMemberSet.Close() + } if closer, ok := m.logOutput.(io.Closer); ok { logErr = closer.Close() } close(m.done) - if serveErr != nil || logErr != nil || handlerErr != nil { - return fmt.Errorf("closing server: '%v', closing logs: '%v', closing handler: '%v'", serveErr, logErr, handlerErr) + if serveErr != nil || logErr != nil || handlerErr != nil || gossipErr != nil { + return fmt.Errorf("closing server: '%v', closing logs: '%v', closing handler: '%v', closing gossip: '%v'", serveErr, logErr, handlerErr, gossipErr) } return nil }