From df2561f6a267cebffc59f6e248e25c7934880a7a Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Mon, 6 Mar 2023 09:57:28 -0500 Subject: [PATCH] ipn/ipnlocal: stop netmap expiry timer when resetting control client This prevents a panic where we synthesize a new netmap in setClientStatus after we've shut down and nil'd out the controlclient, since that function expects to be called while connected to control. Fixes #7392 Signed-off-by: Andrew Dunham Change-Id: Ib631eb90f34f6afa008d69bbb386f70da145e102 --- ipn/ipnlocal/local.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 8e9192d2d..6502275ca 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -3682,6 +3682,21 @@ func (b *LocalBackend) resetControlClientLockedAsync() { if b.cc == nil { return } + + // When we clear the control client, stop any outstanding netmap expiry + // timer; synthesizing a new netmap while we don't have a control + // client will break things. + // + // See https://github.com/tailscale/tailscale/issues/7392 + if b.nmExpiryTimer != nil { + b.nmExpiryTimer.Stop() + b.nmExpiryTimer = nil + + // Also bump the epoch to ensure that if the timer started, it + // will abort. + b.numClientStatusCalls.Add(1) + } + go b.cc.Shutdown() b.cc = nil b.ccAuto = nil