From 3a426a40b66b248631375ed26f2de5c0b3d3dc09 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Thu, 6 May 2021 01:28:43 -0400 Subject: [PATCH] ipnlocal: fix deadlock in RequestEngineStatusAndWait() error path. If the engine was shutting down from a previous session (e.closing=true), it would return an error code when trying to get status. In that case, ipnlocal would never unblock any callers that were waiting on the status. Not sure if this ever happened in real life, but I accidentally triggered it while writing a test. Signed-off-by: Avery Pennarun --- ipn/ipnlocal/local.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 27c61f3ee..f2ea76f16 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -566,10 +566,18 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) { if err != nil { b.logf("wgengine status error: %v", err) + + b.statusLock.Lock() + b.statusChanged.Broadcast() + b.statusLock.Unlock() return } if s == nil { b.logf("[unexpected] non-error wgengine update with status=nil: %v", s) + + b.statusLock.Lock() + b.statusChanged.Broadcast() + b.statusLock.Unlock() return }