From c8d4cfb5eec22829b99ff97167622b4a2df87e37 Mon Sep 17 00:00:00 2001 From: Francois Marier Date: Thu, 20 Aug 2026 14:55:49 -0700 Subject: [PATCH] net/portmapper: invalidate UPnP mappings asynchronously invalidateMappingsLocked() makes network requests to invalidate any active port mappings. Releasing NAT-PMP and PCP mappings never blocks, but UPnP mappings did block and a slow/non-responding router could deadlock this code. Since these invalidations are supposed to be best-effort fire-and- forget, there is no reason to block on them. Calling Release() in a separate goroutine means that we can immediately forget the old mappings and release the lock. Fixes https://github.com/tailscale/corp/issues/33619 Change-Id: I6d8e53aa104416bc2c63809381f798568353ba7f Signed-off-by: Francois Marier --- net/portmapper/portmapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index 37d7730c5..6cdbe6c40 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -394,7 +394,7 @@ func (c *Client) listenPacket(ctx context.Context, network, addr string) (nettyp func (c *Client) invalidateMappingsLocked(releaseOld bool) { if c.mapping != nil { if releaseOld { - c.mapping.Release(context.Background()) + go c.mapping.Release(context.Background()) } c.mapping = nil }