diff --git a/control/controlclient/auto.go b/control/controlclient/auto.go index be80fd791..a87e96e6e 100644 --- a/control/controlclient/auto.go +++ b/control/controlclient/auto.go @@ -668,37 +668,35 @@ func (c *Auto) UpdateEndpoints(endpoints []tailcfg.Endpoint) { } func (c *Auto) Shutdown() { - c.logf("client.Shutdown()") - c.mu.Lock() - closed := c.closed + if c.closed { + c.mu.Unlock() + return + } + c.logf("client.Shutdown ...") + direct := c.direct - if !closed { - c.closed = true - c.observerQueue.Shutdown() - c.cancelAuthCtxLocked() - c.cancelMapCtxLocked() - for _, w := range c.unpauseWaiters { - w <- false - } - c.unpauseWaiters = nil + c.closed = true + c.observerQueue.Shutdown() + c.cancelAuthCtxLocked() + c.cancelMapCtxLocked() + for _, w := range c.unpauseWaiters { + w <- false } + c.unpauseWaiters = nil c.mu.Unlock() - c.logf("client.Shutdown") - if !closed { - c.unregisterHealthWatch() - <-c.authDone - <-c.mapDone - <-c.updateDone - if direct != nil { - direct.Close() - } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - c.observerQueue.Wait(ctx) - c.logf("Client.Shutdown done.") + c.unregisterHealthWatch() + <-c.authDone + <-c.mapDone + <-c.updateDone + if direct != nil { + direct.Close() } + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + c.observerQueue.Wait(ctx) + c.logf("Client.Shutdown done.") } // NodePublicKey returns the node public key currently in use. This is