From 0f7e7c333ad8453d699a5310910ea07a63ae5cb2 Mon Sep 17 00:00:00 2001 From: Nick Khyl Date: Mon, 16 Jun 2025 17:49:03 -0500 Subject: [PATCH] ipn/ipnlocal: ensure b.mu is always unlocked in (*LocalBackend).authReconfig Updates tailscale/corp#27502 (caused a deadlock in a test while working on it) Signed-off-by: Nick Khyl --- ipn/ipnlocal/local.go | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index cd30e92bb..2e620c8d7 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -4857,19 +4857,34 @@ func (b *LocalBackend) readvertiseAppConnectorRoutes() { // updates are not currently blocked, based on the cached netmap and // user prefs. func (b *LocalBackend) authReconfig() { - b.mu.Lock() - blocked := b.blocked - prefs := b.pm.CurrentPrefs() - cn := b.currentNode() - nm := cn.NetMap() - hasPAC := b.prevIfState.HasPAC() - disableSubnetsIfPAC := cn.SelfHasCap(tailcfg.NodeAttrDisableSubnetsIfPAC) - dohURL, dohURLOK := cn.exitNodeCanProxyDNS(prefs.ExitNodeID()) - dcfg := cn.dnsConfigForNetmap(prefs, b.keyExpired, b.logf, version.OS()) - // If the current node is an app connector, ensure the app connector machine is started - b.reconfigAppConnectorLocked(nm, prefs) - closing := b.shutdownCalled - b.mu.Unlock() + var ( + blocked bool + prefs ipn.PrefsView + hasPAC bool + cn *nodeBackend + nm *netmap.NetworkMap + disableSubnetsIfPAC bool + dohURL string + dohURLOK bool + dcfg *dns.Config + closing bool + ) + + func() { // make sure b.mu gets unlocked if anything below panics + b.mu.Lock() + defer b.mu.Unlock() + blocked = b.blocked + prefs = b.pm.CurrentPrefs() + cn = b.currentNode() + nm = cn.NetMap() + hasPAC = b.prevIfState.HasPAC() + disableSubnetsIfPAC = cn.SelfHasCap(tailcfg.NodeAttrDisableSubnetsIfPAC) + dohURL, dohURLOK = cn.exitNodeCanProxyDNS(prefs.ExitNodeID()) + dcfg = cn.dnsConfigForNetmap(prefs, b.keyExpired, b.logf, version.OS()) + // If the current node is an app connector, ensure the app connector machine is started + b.reconfigAppConnectorLocked(nm, prefs) + closing = b.shutdownCalled + }() if closing { b.logf("[v1] authReconfig: skipping because in shutdown")