From c6756a82c32ca75b47917702f95ffe1067685266 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 00065623a..dbd563adf 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 }